Advertisement
DieFeM

Parse TS Blueprint (Connected Object Check)

Jul 3rd, 2019
227
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pascal 20.89 KB | None | 0 0
  1. unit ParseTSBlueprint;
  2.  
  3. // TJsonObject casts:
  4.  
  5. // S string
  6. // I Integer
  7. // L Int64
  8. // U UInt64
  9. // F Double
  10. // D TDateTime
  11. // D Utc TDateTime
  12. // B Boolean
  13. // A TJsonArray
  14. // O TJsonObject
  15.  
  16. // Castle workshop ref 00066EB6 (for powering reference)
  17.  
  18. // Automation Tools Functions
  19. {
  20.   ConstructOkCancelButtons:
  21.   A procedure which makes the standard OK and Cancel buttons on a form.
  22.  
  23.   Example usage:
  24.   ConstructOkCancelButtons(frm, pnlBottom, frm.Height - 80);
  25. }
  26. procedure ConstructOkCancelButtons(h: TObject; p: TObject; top: Integer);
  27. var
  28.   btnOk: TButton;
  29.   btnCancel: TButton;
  30. begin
  31.   btnOk := TButton.Create(h);
  32.   btnOk.Parent := p;
  33.   btnOk.Caption := 'OK';
  34.   btnOk.ModalResult := mrOk;
  35.   btnOk.Left := h.Width div 2 - btnOk.Width - 8;
  36.   btnOk.Top := top;
  37.  
  38.   btnCancel := TButton.Create(h);
  39.   btnCancel.Parent := p;
  40.   btnCancel.Caption := 'Cancel';
  41.   btnCancel.ModalResult := mrCancel;
  42.   btnCancel.Left := btnOk.Left + btnOk.Width + 16;
  43.   btnCancel.Top := btnOk.Top;
  44. end;
  45.  
  46. {
  47.   ConstructLabel:
  48.   A function which can be used to make a label.  Used to make code more compact.
  49.  
  50.   Example usage:
  51.   lbl3 := ConstructLabel(frm, pnlBottom, 65, 8, 360, 'Reference removal options:');
  52. }
  53. function ConstructLabel(h: TObject; p: TObject; top: Integer; left: Integer; width: Integer; height: Integer; s: String): TLabel;
  54. var
  55.   lb: TLabel;
  56. begin
  57.   lb := TLabel.Create(h);
  58.   lb.Parent := p;
  59.   lb.Top := top;
  60.   lb.Left := left;
  61.   lb.Width := width;
  62.   if (height > 0) then
  63.     lb.Height := height;
  64.   lb.Caption := s;
  65.  
  66.   Result := lb;
  67. end;
  68.  
  69. {
  70.   HexFormID
  71.   Gets the formID of a record as a hexadecimal string.
  72.  
  73.   This is useful for just about every time you want to deal with FormIDs.
  74.  
  75.   Example usage:
  76.   s := HexFormID(e);
  77. }
  78. function HexFormID(e: IInterface): string;
  79. var
  80.   s: string;
  81. begin
  82.   s := GetElementEditValues(e, 'Record Header\FormID');
  83.   if SameText(Signature(e), '') then
  84.     Result := '00000000'
  85.   else  
  86.     Result := Copy(s, Pos('[' + Signature(e) + ':', s) + Length(Signature(e)) + 2, 8);
  87. end;
  88.  
  89. // End of Automation Tools Functions
  90.  
  91. procedure SplitText(const s: String; aList: TStringList);
  92. begin
  93.   aList.Delimiter := '|';
  94.   aList.StrictDelimiter := True; // Spaces excluded from being a delimiter
  95.   aList.DelimitedText := s;
  96. end;
  97.  
  98. function GetPluginIndex(PluginName: string): integer;
  99. var
  100.   i, pi : integer;
  101. begin
  102.   pi := -1;
  103.   for i := Pred(FileCount) downto 0 do
  104.     if SameText(PluginName, GetFileName(FileByIndex(i))) then begin
  105.       pi := i;
  106.       Break;
  107.     end;
  108.   Result := pi;
  109. end;
  110.  
  111. function GetWorkshopRef(PluginIndex: integer; WorkshopID:string): IInterface;
  112. var
  113.   fid: integer;
  114.   f: IInterface;
  115. begin
  116.   f := FileByIndex(PluginIndex);
  117.   fid := StrToInt64('$' + IntToHex(GetLoadOrder(f), 2) + WorkshopID);
  118.   Result := RecordByFormID(f, fid, True);
  119. end;
  120.  
  121. procedure AddOrAssign(r: IInterface; container: string; element: string; value: string);
  122. var
  123.   el: IInterface;
  124. begin
  125.   if ElementExists(r, container) then begin
  126.     el := ElementByPath(r, container);
  127.     el := ElementAssign(el, HighInteger, nil, False);
  128.     if Assigned(el) then begin
  129.       SetElementEditValues(el, element, value);
  130.     end;
  131.   end
  132.   else begin
  133.     el := Add(r, container, True);
  134.     if Assigned(el) then begin
  135.       SetElementEditValues(ElementByIndex(el, 0), element, value);
  136.     end;
  137.   end;
  138. end;
  139.  
  140. procedure AddToPowerGrid(workshopRef: IInterface; Node1Ref: IInterface; Node2Ref: IInterface; LineRef: IInterface);
  141. var
  142.   el: IInterface;
  143. begin
  144.   if ElementExists(workshopRef, 'Power Grid') then begin
  145.     el := ElementByPath(workshopRef, 'Power Grid');
  146.     SetElementNativeValues(el, 'XWPG', GetElementNativeValues(el, 'XWPG') + 1);
  147.     el := ElementByPath(el, 'Connections');
  148.     if Assigned(el) then begin
  149.       el := ElementAssign(el, HighInteger, nil, False);
  150.       if Assigned(el) then begin
  151.         if Node1Ref <> nil then
  152.           SetElementEditValues(el, 'Node 1', Name(Node1Ref));
  153.         if Node2Ref <> nil then
  154.           SetElementEditValues(el, 'Node 2', Name(Node2Ref));
  155.         if LineRef <> nil then
  156.           SetElementEditValues(el, 'Line', Name(LineRef));
  157.       end;
  158.     end;
  159.   end
  160.   else begin
  161.     el := Add(workshopRef, 'Power Grid', True);
  162.     if Assigned(el) then begin
  163.       SetElementEditValues(el, 'XWPG', '1');
  164.       el := Add(el, 'XWPN', False);
  165.       if Assigned(el) then begin
  166.         SetElementEditValues(el, 'XWPN\Node 1', Name(Node1Ref));
  167.         SetElementEditValues(el, 'XWPN\Node 2', Name(Node2Ref));
  168.         if LineRef <> nil then
  169.           SetElementEditValues(el, 'XWPN\Line', Name(LineRef));
  170.       end;
  171.     end;
  172.   end;
  173. end;
  174.  
  175. procedure ListAVandKW(rec: IInterface ;sl :TStringList);
  176. var
  177.   j: integer;
  178.   element: IInterface;
  179. begin
  180.   element := ElementByPath(rec, 'PRPS');
  181.   if Assigned(element) then begin
  182.     j := 0;
  183.     while j < ElementCount(element) do begin
  184.       sl.Add(GetElementEditValues(ElementByIndex(element, j), 'Actor Value'));
  185.       Inc(j);
  186.     end;
  187.   end;
  188.   element := ElementByPath(rec, 'KWDA');
  189.   if Assigned(element) then begin
  190.     j := 0;
  191.     while j < ElementCount(element) do begin
  192.       sl.Add(GetEditValue(ElementByIndex(element, j)));
  193.       Inc(j);
  194.     end;
  195.   end;
  196. end;
  197.  
  198. procedure SetFlag(elem: IInterface; flagName: string; flagValue: boolean);
  199. var
  200.   sl: TStringList;
  201.   i: Integer;
  202.   f, f2: Cardinal;
  203. begin
  204.   sl := TStringList.Create;
  205.   sl.Text := FlagValues(elem);
  206.   f := GetNativeValue(elem);
  207.   for i := 0 to Pred(sl.Count) do
  208.     if SameText(sl[i], flagName) then begin
  209.       if flagValue then
  210.         f2 := f or (1 shl i)
  211.       else
  212.         f2 := f and not (1 shl i);
  213.       if f <> f2 then SetNativeValue(elem, f2);
  214.       Break;
  215.     end;
  216.   sl.Free;
  217. end;
  218.  
  219. function StripNonAlpha(const AValue: string): string;
  220. var
  221.   regexp: TPerlRegEx;
  222. begin
  223.   regexp := TPerlRegEx.Create;
  224.   try
  225.     regexp.Subject := AValue;
  226.     regexp.RegEx := '([^a-zA-Z0-9]+)';
  227.     regexp.Options := [preCaseLess];
  228.     regexp.ReplaceAll;
  229.     Result := regexp.Subject;
  230.   finally
  231.     regexp.Free;
  232.   end;
  233. end;
  234.  
  235. function GetWorkshopRefDup(workshopRef: IInterface; workshoptype: integer; ToFile: IInterface): IInterface;
  236. var
  237.   element, baseObj1, baseObj2, workshopRefDup: IInterface;
  238.   i: integer;
  239. begin
  240.   if workshoptype = 0 then begin
  241.     AddMessage('Workshop Type: Copy record for workshop ref as dual workshop.');
  242.     workshopRefDup := wbCopyElementToFile(workshopRef, ToFile, True, True);// Copy record for workshop ref as new record
  243.    
  244.     baseObj1 := LinksTo(ElementByName(workshopRef, 'NAME - Base')); // Get the workshop base object
  245.     baseObj1 := wbCopyElementToFile(baseObj1, ToFile, True, True); // Copy record for workshop base object
  246.     SetElementEditValues(baseObj1, 'EDID', GetElementEditValues(baseObj1, 'EDID') + '_' + StripNonAlpha(GetFileName(ToFile))); // Add suffix to the EDID of our copied workshop base object
  247.     baseObj2 := RecordByFormID(FileByIndex(0), StrToInt64('$0023F662'), False); // Get the base object of the invisible chest
  248.     SetElementEditValues(baseObj1, 'Model\MODL', GetElementEditValues(baseObj2, 'Model\MODL')); // Set the model of the duplicate workshop base object as a invisible chest
  249.     SetElementEditValues(workshopRefDup, 'NAME', HexFormID(baseObj1)); // Set our custom workshop base object for our duplicated workshop ref.
  250.     SetElementEditValues(workshopRefDup, 'EDID', GetElementEditValues(workshopRef, 'EDID') + '_' + StripNonAlpha(GetFileName(ToFile))); // Set the base object of the duplicate workshop as a invisible chest
  251.    
  252.     element := Add(workshopRefDup, 'Linked References', True); // Link the duplicated workshop to the actual workshop
  253.     if Assigned(element) then begin
  254.       SetElementEditValues(element, 'XLKR\Keyword/Ref', '00054BA6');
  255.       SetElementEditValues(element, 'XLKR\Ref', Name(workshopRef));
  256.     end;
  257.   end
  258.   else if workshoptype = 1 then begin
  259.     AddMessage('Workshop Type: Copy record for workshop ref as complete replacement');
  260.     workshopRefDup := wbCopyElementToFile(workshopRef, ToFile, True, True);// Copy record for workshop ref as new record
  261.     // redirect 'referenced by' workshop records
  262.     for i := Pred(ReferencedByCount(workshopRef)) downto 0 do begin
  263.       baseObj1 := ReferencedByIndex(workshopRef, i);
  264.       AddMasterIfMissing(ToFile, GetFileName(GetFile(baseObj1)));
  265.       baseObj1 := wbCopyElementToFile(baseObj1, ToFile, False, True);
  266.       CompareExchangeFormID(baseObj1, GetLoadOrderFormID(workshopRef), GetLoadOrderFormID(workshopRefDup));
  267.     end;
  268.     workshopRef := wbCopyElementToFile(workshopRef, ToFile, False, True);// Copy record for workshop ref as override
  269.     SetFlag(ElementByPath(workshopRef, 'Record Header\Record Flags'), 'Deleted', true); // Flag the workshop override as deleted
  270.   end
  271.   else if workshoptype = 2 then begin
  272.     AddMessage('Workshop Type: Override record for workshop ref');
  273.     workshopRefDup := wbCopyElementToFile(workshopRef, ToFile, False, True);// Copy record for workshop ref as override
  274.   end;
  275.   Result := workshopRefDup;
  276. end;
  277.  
  278. procedure BeginImport(bppath: string; ToFile: IInterface; workshoptype: integer);
  279. var
  280.   BP, obj: TJsonObject;
  281.   form_id, reftype: string;
  282.   items: TJsonArray;
  283.   j, i, pi: integer;
  284.   element, workshopRef, workshopRefDup, wscell, ref, refA, refB, baseObj: IInterface;
  285.   sl: TStringList;
  286. begin
  287.   BP := TJsonObject.Create;
  288.   try
  289.     // parse the blueprint in the path given by the argument bppath (relative to Data)
  290.     BP.LoadFromResource(bppath);
  291.     pi := GetPluginIndex(BP.O['header'].S['worldspace_plugin']);
  292.     workshopRef := GetWorkshopRef(pi, BP.O['workshop'].S['id']);
  293.     wscell := LinksTo(ElementByName(workshopRef, 'Cell'));
  294.     AddMasterIfMissing(ToFile, GetFileName(GetFile(wscell)));
  295.     // Copy the workshop cell as override record and store the cell's persistent group in wscell
  296.     wscell := wbCopyElementToFile(ElementByIndex(ChildGroup(wscell), 0), ToFile, True, False);
  297.    
  298.     // Add Fallout4.esm as master beforehand because the first record copied
  299.     // could be from another file and it may contain references to records of Fallout4.esm
  300.     AddMasterIfMissing(ToFile, GetFileName(FileByIndex(0)));
  301.    
  302.     WorkshopRefDup := GetWorkshopRefDup(workshopRef, workshoptype, ToFile);
  303.    
  304.     items := BP.A['items'];
  305.     i := 0;
  306.     while i < items.Count do begin
  307.       obj := items.O[i];
  308.       pi := GetPluginIndex(obj.S['plugin_name']);
  309.       if pi = -1 then begin
  310.         AddMessage(obj.S['plugin_name'] + ' Plugin Not Found');
  311.       end
  312.       else begin
  313.           form_id := IntToHex(GetLoadOrder(FileByIndex(pi)), 2) + obj.S['FormID'];
  314.           baseObj := RecordByFormID(FileByIndex(pi), StrToInt64('$' + form_id), False);
  315.          
  316.           sl := TStringList.Create;
  317.           ReportRequiredMasters(baseObj, sl, false, false);
  318.           j := 0;
  319.           while j < sl.Count do begin
  320.             AddMasterIfMissing(ToFile, sl[j]);
  321.             Inc(j);
  322.           end;
  323.           sl.Free;
  324.          
  325.           if Signature(baseObj) = 'NPC_' then reftype := 'ACHR' else reftype := 'REFR';
  326.          
  327.           ref := Add(wscell, reftype, True);
  328.           SetElementEditValues(ref, 'NAME', form_id);
  329.           SetElementEditValues(ref, 'DATA\Position\X', obj.S['posX']);
  330.           SetElementEditValues(ref, 'DATA\Position\Y', obj.S['posY']);
  331.           SetElementEditValues(ref, 'DATA\Position\Z', obj.S['posZ']);
  332.           SetElementEditValues(ref, 'DATA\Rotation\X', obj.S['rotX']);
  333.           SetElementEditValues(ref, 'DATA\Rotation\Y', obj.S['rotY']);
  334.           SetElementEditValues(ref, 'DATA\Rotation\Z', obj.S['rotZ']);
  335.          
  336.           if obj.S['Scale'] <> '1.0' then begin
  337.             element := Add(ref, 'XSCL', True);
  338.             if Assigned(element) then
  339.               SetEditValue(element, obj.S['Scale']);
  340.           end;
  341.          
  342.           element := Add(ref, 'Linked References', True);
  343.           if Assigned(element) then begin
  344.             SetElementEditValues(element, 'XLKR\Keyword/Ref', '00054BA6');
  345.             SetElementEditValues(element, 'XLKR\Ref', Name(workshopRefDup));
  346.           end;
  347.          
  348.           obj.S['RefId'] := IntToHex(GetLoadOrderFormID(ref), 8);
  349.       end;
  350.       Inc(i);
  351.     end;
  352.    
  353.     // Start Powering Phase While
  354.     i := 0;
  355.     while i < items.Count do begin
  356.       obj := items.O[i];
  357.      
  358.       // Start if refid is not 0
  359.       if obj.S['RefId'] <> '' then begin
  360.      
  361.         refA := RecordByFormID(ToFile, StrToInt64('$' + obj.S['RefId']), True);
  362.        
  363.         // Start if Cables else Objects
  364.         // Start Cables
  365.         if obj.S['ConnectedObjects'] <> '' then begin
  366.          
  367.           sl := TStringList.Create;
  368.           SplitText(obj.S['ConnectedObjects'], sl);
  369.          
  370.           // Loop Connected Objects
  371.           j := 0;
  372.           while j < sl.Count do begin
  373.             // Start (Is Connected Object with greater Index)
  374.             if StrToInt(sl[j]) > i then begin
  375.              
  376.               // Start Check if connected object has a reference
  377.               if items.O[StrToInt(sl[j])].S['RefId'] <> '' then begin
  378.                
  379.                 // Get Connected Object Ref
  380.                 refB := RecordByFormID(ToFile, StrToInt64('$' + items.O[StrToInt(sl[j])].S['RefId']), True);
  381.                
  382.                 // Create Spline
  383.                 ref := Add(wscell, 'REFR', True);
  384.                 SetElementEditValues(ref, 'NAME', '0001D971');
  385.                 SetElementNativeValues(ref, 'DATA\Position\X', StrToFloat(obj.S['posX']) + ((GetElementNativeValues(refB, 'DATA\Position\X') - GetElementNativeValues(refA, 'DATA\Position\X'))/2));
  386.                 SetElementNativeValues(ref, 'DATA\Position\Y', StrToFloat(obj.S['posY']) + ((GetElementNativeValues(refB, 'DATA\Position\Y') - GetElementNativeValues(refA, 'DATA\Position\Y'))/2));
  387.                 SetElementNativeValues(ref, 'DATA\Position\Z', StrToFloat(obj.S['posZ']) + ((GetElementNativeValues(refB, 'DATA\Position\Z') - GetElementNativeValues(refA, 'DATA\Position\Z'))/2));
  388.                 SetElementEditValues(ref, 'DATA\Rotation\X', '0.0');
  389.                 SetElementEditValues(ref, 'DATA\Rotation\Y', '0.0');
  390.                 SetElementEditValues(ref, 'DATA\Rotation\Z', '0.0');
  391.                
  392.                 // Link Spline ref to workshop
  393.                 element := Add(ref, 'Linked References', True);
  394.                 if Assigned(element) then begin
  395.                   SetElementEditValues(element, 'XLKR\Keyword/Ref', '00054BA6');
  396.                   SetElementEditValues(element, 'XLKR\Ref', Name(workshopRefDup));
  397.                 end;
  398.                
  399.                 // Set Spline Values
  400.                 element := Add(ref, 'XBSD', True);
  401.                 if Assigned(element) then begin
  402.                   // Slack
  403.                   SetEditValue(ElementByIndex(element, 0), '0.051149');
  404.                   // Thickness
  405.                   SetEditValue(ElementByIndex(element, 1), '1.500000');
  406.                   // ? Other point Relative X
  407.                   SetNativeValue(ElementByIndex(element, 2), (GetElementNativeValues(refB, 'DATA\Position\X') - GetElementNativeValues(refA, 'DATA\Position\X'))/2);
  408.                   // ? Other point Relative Y
  409.                   SetNativeValue(ElementByIndex(element, 3), (GetElementNativeValues(refB, 'DATA\Position\Y') - GetElementNativeValues(refA, 'DATA\Position\Y'))/2);
  410.                   // ? Other point Relative Z
  411.                   SetNativeValue(ElementByIndex(element, 4), (GetElementNativeValues(refB, 'DATA\Position\Z') - GetElementNativeValues(refA, 'DATA\Position\Z'))/2);
  412.                   // Detached End
  413.                   SetEditValue(ElementByIndex(element, 5), 'False');
  414.                 end;
  415.                
  416.                 // Set Spline Connections
  417.                 AddOrAssign(ref, 'Spline Connection', 'Ref', Name(refA));
  418.                 AddOrAssign(ref, 'Spline Connection', 'Ref', Name(refB));
  419.                 AddOrAssign(refA, 'Spline Connection', 'Ref', Name(ref));
  420.                 AddOrAssign(refB, 'Spline Connection', 'Ref', Name(ref));
  421.                
  422.                 // Setup Grid
  423.                 AddToPowerGrid(workshopRefDup, refA, refB, ref);
  424.               // End Check if connected object has a reference
  425.               end;
  426.             // End (Is Connected Object with greater Index)
  427.             end;
  428.             Inc(j);
  429.           // End Loop Connected Objects
  430.           end;
  431.           sl.Free;
  432.         // End Cables
  433.         end
  434.         // Start Objects
  435.         else begin
  436.           // Start If assigned radiator
  437.           if obj.I['isPowered'] = 1 then
  438.             AddToPowerGrid(workshopRefDup, refA, workshopRefDup, nil);
  439.         // End Objects
  440.         // End if Cables else Objects
  441.         end;
  442.        
  443.         // Give power to snapped connections
  444.         pi := GetPluginIndex(obj.S['plugin_name']);
  445.         form_id := IntToHex(GetLoadOrder(FileByIndex(pi)), 2) + obj.S['FormID'];
  446.         baseObj := RecordByFormID(FileByIndex(pi), StrToInt64('$' + form_id), False);
  447.         sl := TStringList.Create;
  448.         ListAVandKW(baseObj, sl);
  449.         if sl.IndexOf('WorkshopSnapTransmitsPower [AVIF:00000354]') > -1 then
  450.           AddToPowerGrid(workshopRefDup, refA, workshopRefDup, nil);
  451.         sl.Free;
  452.       // End if refid is not 0
  453.       end;
  454.       Inc(i);
  455.     // End Powering Phase While
  456.     end;
  457.   finally
  458.     BP.Free;
  459.   end;
  460. end;
  461.  
  462. function SelectWorkshopType(): integer;
  463. var
  464.   frm: TForm;
  465.   lbl: TLabel;
  466.   cbFiles: TComboBox;
  467. begin
  468.   frm := TForm.Create(nil);
  469.   try
  470.     frm.Caption := 'Select Workshop Type';
  471.     frm.Width := 500;
  472.     frm.Height := 160;
  473.     frm.Position := poScreenCenter;
  474.    
  475.     lbl := ConstructLabel(frm, frm, 8, 8, 284, 30, 'Workshop Type:');
  476.    
  477.     cbFiles := TComboBox.Create(frm);
  478.     cbFiles.Parent := frm;
  479.     cbFiles.Items.Add('Dual Workshop (two workshops in 1 settlement (2nd hidden), has own stats)');
  480.     cbFiles.Items.Add('Complete Replacement (redirects references, can produce incompatibilities)');
  481.     cbFiles.Items.Add('Override Record (optimal, only new game, saved game = no power)');
  482.     cbFiles.Top := lbl.Top + lbl.Height + 20;
  483.     cbFiles.Left := 8;
  484.     cbFiles.Width := 400;
  485.     cbFiles.ItemIndex := 0;
  486.        
  487.     ConstructOkCancelButtons(frm, frm, 80);
  488.    
  489.     if frm.ShowModal = mrOk then
  490.       Result := cbFiles.ItemIndex
  491.     else
  492.       Result := -1;
  493.   finally
  494.     frm.Free;
  495.   end;
  496. end;
  497.  
  498. function CreateSelector(Blueprints: TwbFastStringList; var bppath: string): integer;
  499. var
  500.   frm: TForm;
  501.   lbl: TLabel;
  502.   cbFiles: TComboBox;
  503.   btnOk, btnCancel: TButton;
  504.   i: integer;
  505.   s: string;
  506. begin
  507.   frm := TForm.Create(nil);
  508.   try
  509.     frm.Caption := 'Select Blueprint';
  510.     frm.Width := 550;
  511.     frm.Height := 170;
  512.     frm.Position := poScreenCenter;
  513.    
  514.     lbl := ConstructLabel(frm, frm, 8, 8, 284, 30, 'Blueprint');
  515.    
  516.     cbFiles := TComboBox.Create(frm);
  517.     cbFiles.Parent := frm;
  518.     cbFiles.Top := lbl.Top + lbl.Height + 20;
  519.     cbFiles.Left := 8;
  520.     cbFiles.Width := 500;
  521.    
  522.     for i := 0 to Pred(Blueprints.Count) do
  523.       cbFiles.Items.Add(Blueprints[i]);
  524.    
  525.     cbFiles.ItemIndex := 0;
  526.    
  527.     ConstructOkCancelButtons(frm, frm, cbFiles.Top + 40);
  528.    
  529.     if frm.ShowModal = mrOk then begin
  530.       bppath := cbFiles.Text;
  531.       Result := 0;
  532.     end
  533.     else Result := 1;
  534.   finally
  535.     frm.Free;
  536.   end;
  537. end;
  538.  
  539. function SelectBlueprint(var bppath: string): integer;
  540. var
  541.   i: integer;
  542.   slContainers: TStringList;
  543.   Blueprints, slAssets: TwbFastStringList;
  544.   r: integer;
  545. begin
  546.   slContainers := TStringList.Create;
  547.   slAssets := TwbFastStringList.Create;
  548.   Blueprints := TwbFastStringList.Create;
  549.  
  550.   ResourceContainerList(slContainers);
  551.  
  552.   for i := 0 to Pred(slContainers.Count) do
  553.     if ExtractFileName(slContainers[i]) = '' then
  554.       ResourceList(slContainers[i], slAssets);
  555.  
  556.   slAssets.Sort;
  557.   wbRemoveDuplicateStrings(slAssets);
  558.  
  559.   for i := 0 to Pred(slAssets.Count) do
  560.     if ContainsText(slAssets[i], 'F4SE\Plugins\TransferSettlements\blueprints') then
  561.       Blueprints.Add(slAssets[i]);
  562.  
  563.   if Blueprints.Count > 0 then begin
  564.     r := CreateSelector(Blueprints, bppath);
  565.   end
  566.   else
  567.     r := 2;
  568.   slAssets.Free;
  569.   slContainers.Free;
  570.   Result := r;
  571. end;
  572.  
  573. // in the initialization it just shows a dialogue to enter the path of the blueprint
  574. // and calls BeginImport with the given path
  575. function Initialize: Integer;
  576. var
  577.   s: string;
  578.   r, w: integer;
  579.   f: IInterface;
  580. begin
  581.   r := SelectBlueprint(s);
  582.   if r = 0 then begin
  583.     if ResourceExists(s) then begin
  584.       w := SelectWorkshopType();
  585.       if w <> -1 then begin
  586.          f := AddNewFile; //Shows a dialog to create a new esp.
  587.          if f <> nil then BeginImport(s, f, w) else AddMessage('Invalid File Name.');
  588.       end
  589.       else AddMessage('Import canceled.');
  590.     end
  591.     else
  592.       AddMessage('File ' + s + ' could not be found in the Data folder.');
  593.   end
  594.   else if r = 1 then
  595.     AddMessage('Import canceled.')
  596.   else
  597.     AddMessage('No blueprints found.');
  598.  
  599.   Result := 1;
  600. end;
  601.  
  602. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement