Advertisement
DieFeM

Copy World Refs To Interior

Dec 29th, 2022
2,211
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pascal 11.86 KB | None | 0 0
  1. {
  2.   Copy references from selected containers to a given interior cell.
  3. }
  4. unit CopyWorldRefsToInterior;
  5.  
  6. var
  7.     f: IwbFile;
  8.     cell: IInterface;
  9.     slCells, slEl, slRefs: TStringList;
  10.     count: integer;
  11.    
  12. procedure SplitText(const s: String; aList: TStringList);
  13. begin
  14.   aList.Delimiter := '|';
  15.   aList.StrictDelimiter := true; // Spaces excluded from being a delimiter
  16.   aList.DelimitedText := s;
  17. end;
  18.    
  19. function GetPluginIndex(PluginName: string): integer;
  20. var
  21.   i, pi : integer;
  22. begin
  23.   pi := -1;
  24.   for i := Pred(FileCount) downto 0 do
  25.     if SameText(PluginName, GetFileName(FileByIndex(i))) then begin
  26.       pi := i;
  27.       Break;
  28.     end;
  29.   Result := pi;
  30. end;
  31.  
  32. function GetRefDoor(ref: IInterface): IInterface;
  33. var
  34.     el, LinkedDoor: IInterface;
  35. begin
  36.     el := ElementByPath(ref, 'XTEL');
  37.     if Assigned(el) then begin
  38.         LinkedDoor := LinksTo(ElementByPath(el, 'Door'));
  39.         if Assigned(LinkedDoor) then begin
  40.             Result := LinkedDoor;
  41.         end;
  42.     end;
  43. end;
  44.  
  45. procedure SetRefDoor(ref: IInterface; door: IInterface);
  46. var
  47.     el: IInterface;
  48. begin
  49.     el := ElementByPath(ref, 'XTEL');
  50.     if Assigned(el) then
  51.         SetElementEditValues(el, 'Door', Name(door));
  52. end;
  53.  
  54. function CalculateToken(e: IInterface): string;
  55. begin
  56.     Result := Format('%d|%s', [
  57.         GetPluginIndex(GetFileName(GetFile(e))),
  58.         IntToStr(FixedFormID(e))
  59.     ]);
  60. end;
  61.  
  62. // Automation Tools Functions
  63. {
  64.   ConstructOkCancelButtons:
  65.   A procedure which makes the standard OK and Cancel buttons on a form.
  66.  
  67.   Example usage:
  68.   ConstructOkCancelButtons(frm, pnlBottom, frm.Height - 80);
  69. }
  70. procedure ConstructOkCancelButtons(h: TObject; p: TObject; top: Integer);
  71. var
  72.   btnOk: TButton;
  73.   btnCancel: TButton;
  74. begin
  75.   btnOk := TButton.Create(h);
  76.   btnOk.Parent := p;
  77.   btnOk.Caption := 'OK';
  78.   btnOk.ModalResult := mrOk;
  79.   btnOk.Left := h.Width div 2 - btnOk.Width - 8;
  80.   btnOk.Top := top;
  81.  
  82.   btnCancel := TButton.Create(h);
  83.   btnCancel.Parent := p;
  84.   btnCancel.Caption := 'Cancel';
  85.   btnCancel.ModalResult := mrCancel;
  86.   btnCancel.Left := btnOk.Left + btnOk.Width + 16;
  87.   btnCancel.Top := btnOk.Top;
  88. end;
  89.  
  90. {
  91.   ConstructLabel:
  92.   A function which can be used to make a label.  Used to make code more compact.
  93.  
  94.   Example usage:
  95.   lbl3 := ConstructLabel(frm, pnlBottom, 65, 8, 360, 'Reference removal options:');
  96. }
  97. function ConstructLabel(h: TObject; p: TObject; top: Integer; left: Integer; width: Integer; height: Integer; s: String): TLabel;
  98. var
  99.   lb: TLabel;
  100. begin
  101.   lb := TLabel.Create(h);
  102.   lb.Parent := p;
  103.   lb.Top := top;
  104.   lb.Left := left;
  105.   lb.Width := width;
  106.   if (height > 0) then
  107.     lb.Height := height;
  108.   lb.Caption := s;
  109.  
  110.   Result := lb;
  111. end;
  112.  
  113. function CreateSelector(title: string; Blueprints: TwbFastStringList; var bppath: string): integer;
  114. var
  115.   frm: TForm;
  116.   lbl: TLabel;
  117.   cbFiles: TComboBox;
  118.   btnOk, btnCancel: TButton;
  119.   i: integer;
  120.   s: string;
  121. begin
  122.   frm := TForm.Create(nil);
  123.   try
  124.     frm.Caption := 'Select ' + title;
  125.     frm.Width := 350;
  126.     frm.Height := 170;
  127.     frm.Position := poScreenCenter;
  128.    
  129.     lbl := ConstructLabel(frm, frm, 15, 15, 0, 0, 'Select ' + title + ':');
  130.    
  131.     cbFiles := TComboBox.Create(frm);
  132.     cbFiles.Parent := frm;
  133.     cbFiles.Top := lbl.Top + lbl.Height + 15;
  134.     cbFiles.Left := 15;
  135.     cbFiles.Width := 300;
  136.     cbFiles.Style := csDropDownList;
  137.    
  138.     for i := 0 to Pred(Blueprints.Count) do
  139.       cbFiles.Items.Add(Blueprints[i]);
  140.    
  141.     cbFiles.ItemIndex := 0;
  142.    
  143.     ConstructOkCancelButtons(frm, frm, cbFiles.Top + 40);
  144.    
  145.     if frm.ShowModal = mrOk then begin
  146.       bppath := cbFiles.Text;
  147.       Result := 0;
  148.     end
  149.     else Result := 1;
  150.   finally
  151.     frm.Free;
  152.   end;
  153. end;
  154.  
  155. function SelectESP(var FileName: string): integer;
  156. var
  157.   i: integer;
  158.   Plugins: TwbFastStringList;
  159.   r: integer;
  160. begin
  161.   Plugins := TwbFastStringList.Create;
  162.   Plugins.Add('<New File>');
  163.   for i := Pred(FileCount) downto 0 do
  164.     if SameText(ExtractFileExt(GetFileName(FileByIndex(i))), '.esp') then
  165.       Plugins.Add(GetFileName(FileByIndex(i)));
  166.  
  167.   r := CreateSelector('Plugin', Plugins, FileName);
  168.  
  169.   Plugins.Free;
  170.   Result := r;
  171. end;
  172.  
  173. function SelectCell(var CellName: string): integer;
  174. var
  175.   i, j, k: integer;
  176.   Cells: TwbFastStringList;
  177.   r: integer;
  178.   ParentCellGroup, ChildCellGroup, CellGroup: IwbGroupRecord;
  179.   tCell: IwbMainRecord;
  180. begin
  181.     Cells := TwbFastStringList.Create;
  182.     slCells := TwbFastStringList.Create;
  183.    
  184.     Cells.Add('<New Cell>');
  185.  
  186.     ParentCellGroup := GroupBySignature(f, 'CELL');
  187.     //AddMessage('ParentCellGroup: ' + IntToStr(ElementCount(ParentCellGroup)));
  188.     for i := 0 to Pred(ElementCount(ParentCellGroup)) do begin
  189.         ChildCellGroup := ElementByIndex(ParentCellGroup, i);
  190.         //AddMessage('ChildCellGroup: ' + IntToStr(ElementCount(ChildCellGroup)));
  191.         for j := 0 to Pred(ElementCount(ChildCellGroup)) do begin
  192.             CellGroup := ElementByIndex(ChildCellGroup, j);
  193.             //AddMessage('CellGroup: ' + IntToStr(ElementCount(CellGroup)));
  194.             for k := 0 to Pred(ElementCount(CellGroup)) do begin
  195.                 tCell := ChildrenOf(ElementByIndex(CellGroup, k));
  196.                 if ElementExists(tCell, 'EDID') then begin
  197.                     Cells.Add(EditorID(tCell));
  198.                     slCells.AddObject(EditorID(tCell), tCell);
  199.                 end;
  200.             end;
  201.         end;
  202.     end;
  203.    
  204.     r := CreateSelector('Cell', Cells, CellName);
  205.  
  206.     Cells.Free;
  207.     Result := r;
  208. end;
  209.  
  210. // Called before processing
  211. // You can remove it if script doesn't require initialization code
  212. function Initialize: integer;
  213. var
  214.     i, fr: integer;
  215.     fname: string;
  216. begin  
  217.     Result := 0;
  218.     count := 0;
  219.    
  220.     fr := SelectESP(fname);
  221.    
  222.     if fr = 0 then begin
  223.        
  224.         if fname = '<New File>' then begin
  225.             f := AddNewFile; //Shows a dialog to create a new esp.
  226.         end
  227.         else begin
  228.             f := FileByIndex(GetPluginIndex(fname));
  229.         end;
  230.        
  231.         if not Assigned(f) then begin
  232.             AddMessage('Invalid File Name.');
  233.             Result := 1;
  234.             exit;
  235.         end;
  236.        
  237.     end
  238.     else begin
  239.         AddMessage('Import canceled.');
  240.         Result := 1;
  241.         exit;
  242.     end;
  243.    
  244.     fr := SelectCell(fname);
  245.    
  246.     if fr = 0 then begin
  247.        
  248.         if fname = '<New Cell>' then begin
  249.             cell := Add(f, 'CELL', true);
  250.             cell := Add(cell, 'CELL', true);
  251.         end
  252.         else begin
  253.             i := slCells.IndexOf(fname);
  254.             if i <> -1 then
  255.                 cell := ObjectToElement(slCells.Objects[i]);
  256.         end;
  257.        
  258.         slCells.Free;
  259.        
  260.         if not Assigned(cell) then begin
  261.             AddMessage('Invalid CELL.');
  262.             Result := 1;
  263.             exit;
  264.         end;
  265.        
  266.     end
  267.     else begin
  268.         AddMessage('Import canceled.');
  269.         Result := 1;
  270.         exit;
  271.     end;
  272.    
  273.     slRefs := TwbFastStringList.Create;
  274.    
  275.     slEl := TwbFastStringList.Create;
  276.     //slEl.Add('Record Header');
  277.     slEl.Add('EDID');
  278.     slEl.Add('VMAD');
  279.     slEl.Add('NAME');
  280.     slEl.Add('XMBO');
  281.     slEl.Add('XPRM');
  282.     slEl.Add('XPOD');
  283.     slEl.Add('XPTL');
  284.     slEl.Add('XORD');
  285.     slEl.Add('XOCP');
  286.     slEl.Add('Bound Data');
  287.     slEl.Add('XMBP');
  288.     slEl.Add('XEZN');
  289.     slEl.Add('XNDP');
  290.     slEl.Add('XRGD');
  291.     slEl.Add('XRGB');
  292.     slEl.Add('Patrol Data');
  293.     slEl.Add('XLCM');
  294.     slEl.Add('XMSP');
  295.     slEl.Add('XCNT');
  296.     slEl.Add('XRDS');
  297.     slEl.Add('XHLT');
  298.     //slEl.Add('Linked References');
  299.     slEl.Add('Patrol');
  300.     slEl.Add('XACT');
  301.     slEl.Add('Activate Parents');
  302.     slEl.Add('XLIB');
  303.     slEl.Add('XATP');
  304.     slEl.Add('XLKT');
  305.     slEl.Add('XRFG');
  306.     slEl.Add('XLYR');
  307.     slEl.Add('XMSP');
  308.     slEl.Add('XRFG');
  309.     slEl.Add('XRDO');
  310.     slEl.Add('XBSD');
  311.     slEl.Add('XPDD');
  312.     slEl.Add('XSPC');
  313.     slEl.Add('XLCN');
  314.     slEl.Add('XTRI');
  315.     slEl.Add('XLOC');
  316.     slEl.Add('XLRL');
  317.     slEl.Add('XLRT');
  318.     slEl.Add('XIS2');
  319.     slEl.Add('Spline Connection');
  320.     slEl.Add('Power Grid');
  321.     slEl.Add('XCVR');
  322.     slEl.Add('XCVL');
  323.     slEl.Add('XCZR');
  324.     slEl.Add('XCZA');
  325.     slEl.Add('XCZC');
  326.     slEl.Add('XSCL');
  327.     //slEl.Add('XLOD');
  328.     slEl.Add('XHTW');
  329.     slEl.Add('XFVC');
  330.     slEl.Add('ONAM');
  331.     slEl.Add('Map Marker');
  332.     //slEl.Add('XATR');
  333.     slEl.Add('XESP');
  334.     slEl.Add('XOWN');
  335.     slEl.Add('XRNK');
  336.     slEl.Add('XEMI');
  337.     slEl.Add('XLIG');
  338.     slEl.Add('Lit Water');
  339.     slEl.Add('XALP');
  340.     slEl.Add('XTEL');
  341.     slEl.Add('XTNM');
  342.     slEl.Add('XMBR');
  343.     slEl.Add('XWCN');
  344.     slEl.Add('XWCU');
  345.     slEl.Add('XASP');
  346.     slEl.Add('XAMC');
  347.     slEl.Add('XIBS');
  348.     slEl.Add('DATA');
  349.     slEl.Add('MNAM');
  350. end;
  351.  
  352. // called for every record selected in xEdit
  353. function Process(e: IInterface): integer;
  354. var
  355.     LinkedDoor, LinkedDoorDup, el, ref : IInterface;
  356.     i: integer;
  357.     token: string;
  358. begin
  359.     Result := 0;
  360.        
  361.     if (Signature(e) = 'ACHR') or (Signature(e) = 'REFR') then begin
  362.        
  363.         //if not ElementExists(e, 'XTEL') then exit;
  364.        
  365.         ref := Add(cell, Signature(e), true);
  366.                
  367.         if not Assigned(ref) then exit;
  368.        
  369.         Inc(count);
  370.        
  371.         AddMessage('Processing: ' + Name(e));
  372.        
  373.         AddRequiredElementMasters(BaseRecord(e), GetFile(f), False);
  374.         AddRequiredElementMasters(e, GetFile(f), False);
  375.                
  376.         i := 0;
  377.         while i < slEl.Count do begin
  378.             if ElementExists(e, slEl.Strings[i]) then begin
  379.                 el := ElementByPath(e, slEl.Strings[i]);
  380.                 if Assigned(el) then begin
  381.                     wbCopyElementToRecord(el, ref, true, true);
  382.                 end;
  383.             end;
  384.             Inc(i);
  385.         end;
  386.                                        
  387.         if GetIsPersistent(e) then
  388.             SetIsPersistent(ref, true);
  389.            
  390.         if ElementExists(ref, 'XTEL') then begin
  391.             LinkedDoor := GetRefDoor(ref);
  392.             AddRequiredElementMasters(LinkedDoor, GetFile(LinkedDoor), False);
  393.             LinkedDoorDup := wbCopyElementToFile(WinningOverride(LinkedDoor), GetFile(f), false, true);
  394.             SetRefDoor(LinkedDoorDup, ref);
  395.         end;
  396.        
  397.         token := CalculateToken(e);
  398.         //AddMessage('Token A: ' + token);
  399.         slRefs.AddObject(token, ref);
  400.            
  401.  
  402.     end;
  403. end;
  404.  
  405. // Called after processing
  406. // You can remove it if script doesn't require finalization code
  407. function Finalize: integer;
  408. var
  409.     RefData: TStringList;
  410.     i, j, k: integer;
  411.     AtRefA, AtRefB, refA, refB: IwbMainRecord;
  412.     LinkedRefA, LinkedRefB, el: IInterface;
  413.     token, id: string;
  414. begin
  415.  
  416.     i := 0;
  417.     while i < slRefs.Count do begin
  418.        
  419.         RefData := TStringList.Create;
  420.         SplitText(slRefs.Strings[i], RefData);
  421.         refA := RecordByFormID(FileByIndex(StrToInt(RefData[0])), StrToInt(RefData[1]), true);
  422.         RefData.Free;
  423.         refB := ObjectToElement(slRefs.Objects[i]);
  424.        
  425.         if ElementExists(refA, 'Linked References') then begin
  426.             el := ElementByPath(refA, 'Linked References');
  427.             if Assigned(el) then begin
  428.                 LinkedRefB := Add(refB, 'Linked References', true);
  429.                 j := 0;
  430.                 while j < ElementCount(el) do begin
  431.                     LinkedRefA := ElementByIndex(el, j);
  432.                     LinkedRefB := ElementByPath(refB, 'Linked References');
  433.                    
  434.                     if j = 0 then begin
  435.                         LinkedRefB := ElementByIndex(LinkedRefB, 0);
  436.                     end
  437.                     else begin
  438.                         LinkedRefB := ElementAssign(LinkedRefB, HighInteger, nil, false);
  439.                     end;
  440.                    
  441.                     SetElementEditValues(LinkedRefB, 'Keyword/Ref', GetElementEditValues(LinkedRefA, 'Keyword/Ref'));
  442.                    
  443.                     AtRefA := LinksTo(ElementByPath(LinkedRefA, 'Ref'));
  444.                     if Assigned(AtRefA) then begin
  445.                         //AddMessage('AtRefA: ' + Name(AtRefA));
  446.                         token := CalculateToken(AtRefA);
  447.                         //AddMessage('Token B: ' + token);
  448.                         k := slRefs.IndexOf(token);
  449.                         if k <> -1 then begin
  450.                             AtRefB := ObjectToElement(slRefs.Objects[k]);
  451.                             SetElementEditValues(LinkedRefB, 'Ref', Name(AtRefB));
  452.                         end;
  453.                     end;
  454.                    
  455.                     Inc(j);
  456.                 end;
  457.             end;
  458.         end;
  459.        
  460.         //AddMessage('refA: ' + Name(refA));
  461.         if ElementExists(refA, 'XATR') then begin
  462.             el := ElementByPath(refA, 'XATR');
  463.             if Assigned(el) then begin
  464.                 el := Add(refB, 'XATR', true);
  465.                 if Assigned(el) then begin
  466.                     AtRefA := LinksTo(ElementByPath(refA, 'XATR'));
  467.                     if Assigned(AtRefA) then begin
  468.                         //AddMessage('AtRefA: ' + Name(AtRefA));
  469.                         token := CalculateToken(AtRefA);
  470.                         //AddMessage('Token B: ' + token);
  471.                         j := slRefs.IndexOf(token);
  472.                         if j <> -1 then begin
  473.                             AtRefB := ObjectToElement(slRefs.Objects[j]);
  474.                             //SetEditValue(el, Name(AtRefB));
  475.                             SetElementEditValues(refB, 'XATR', Name(AtRefB));
  476.                         end;
  477.                     end;
  478.                 end;
  479.             end;
  480.         end;
  481.        
  482.         Inc(i);
  483.     end;
  484.    
  485.     AddMessage('Processed Records: ' + IntToStr(count));
  486.    
  487.     slRefs.Free;
  488.     slEl.Free;
  489.     Result := 0;
  490. end;
  491.  
  492. end.
  493.  
Tags: xEdit
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement