Advertisement
DieFeM

ParseTSBlueprint radiator temporary

Jun 26th, 2019
219
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pascal 16.52 KB | None | 0 0
  1. unit ParseTSBlueprint;
  2.  
  3. // I've copied this from the source code at git to know which is the cast for each type of data.
  4. // Short names
  5. //    property S[const Name: string]: string read GetString write SetString;        // returns '' if property doesn't exist, auto type-cast except for array/object
  6. //    property I[const Name: string]: Integer read GetInt write SetInt;             // returns 0 if property doesn't exist, auto type-cast except for array/object
  7. //    property L[const Name: string]: Int64 read GetLong write SetLong;             // returns 0 if property doesn't exist, auto type-cast except for array/object
  8. //    property U[const Name: string]: UInt64 read GetULong write SetULong;          // returns 0 if property doesn't exist, auto type-cast except for array/object
  9. //    property F[const Name: string]: Double read GetFloat write SetFloat;          // returns 0 if property doesn't exist, auto type-cast except for array/object
  10. //    property D[const Name: string]: TDateTime read GetDateTime write SetDateTime; // returns 0 if property doesn't exist, auto type-cast except for array/object
  11. //    property DUtc[const Name: string]: TDateTime read GetUtcDateTime write SetUtcDateTime; // returns 0 if property doesn't exist, auto type-cast except for array/object
  12. //    property B[const Name: string]: Boolean read GetBool write SetBool;           // returns false if property doesn't exist, auto type-cast with "<>'true'" and "<>0" except for array/object
  13. //    property A[const Name: string]: TJsonArray read GetArray write SetArray;      // auto creates array on first access
  14. //    property O[const Name: string]: TJsonObject read {$IFDEF BCB}GetObj{$ELSE}GetObject{$ENDIF} write SetObject;   // auto creates object on first access
  15. //00066EB6
  16.  
  17. procedure SplitText(const s: String; aList: TStringList);
  18. begin
  19.   aList.Delimiter := '|';
  20.   aList.StrictDelimiter := True; // Spaces excluded from being a delimiter
  21.   aList.DelimitedText := s;
  22. end;
  23.  
  24. function GetPluginIndex(PluginName: string): integer;
  25. var
  26.   i, pi : integer;
  27. begin
  28.   pi := -1;
  29.   for i := Pred(FileCount) downto 0 do
  30.     if SameText(PluginName, GetFileName(FileByIndex(i))) then begin
  31.       pi := i;
  32.       Break;
  33.     end;
  34.   Result := pi;
  35. end;
  36.  
  37. function GetWorkshopRef(PluginIndex: integer; WorkshopID:string): IInterface;
  38. var
  39.   fid: integer;
  40.   f: IInterface;
  41. begin
  42.   f := FileByIndex(PluginIndex);
  43.   fid := StrToInt64('$' + IntToHex(GetLoadOrder(f), 2) + WorkshopID);
  44.   Result := RecordByFormID(f, fid, True);
  45. end;
  46.  
  47. procedure AddOrAssign(r: IInterface; container: string; element: string; value: string);
  48. var
  49.   el: IInterface;
  50. begin
  51.   if ElementExists(r, container) then begin
  52.     el := ElementByPath(r, container);
  53.     el := ElementAssign(el, HighInteger, nil, False);
  54.     if Assigned(el) then begin
  55.       SetElementEditValues(el, element, value);
  56.     end;
  57.   end
  58.   else begin
  59.     el := Add(r, container, True);
  60.     if Assigned(el) then begin
  61.       SetElementEditValues(ElementByIndex(el, 0), element, value);
  62.     end;
  63.   end;
  64. end;
  65.  
  66. procedure BeginImport(bppath: string; ToFile: IInterface);
  67. var
  68.   BP, obj: TJsonObject;
  69.   form_id, reftype: string;
  70.   items: TJsonArray;
  71.   j, i, pi: integer;
  72.   f, lr, workshopRef, workshopRefOverride, ws, wscell, cell, ref, refA, refB, temp, powerRadiator, testPR: IInterface;
  73.   sl: TStringList;
  74.   c: TwbGridCell;
  75.   pos: TwbVector;
  76. begin
  77.   BP := TJsonObject.Create;
  78.   try
  79.     BP.LoadFromResource(bppath); // parse the blueprint in the path given by the argument (relative to data)
  80.     AddMasterIfMissing(ToFile, GetFileName(FileByIndex(0)));
  81.     pi := GetPluginIndex(BP.O['header'].S['worldspace_plugin']);
  82.     f := FileByIndex(pi);
  83.     workshopRef := GetWorkshopRef(pi, BP.O['workshop'].S['id']);
  84.     wscell := LinksTo(ElementByName(workshopRef, 'Cell'));
  85.     AddMasterIfMissing(ToFile, GetFileName(GetFile(wscell)));
  86.     workshopRefOverride := wbCopyElementToFile(workshopRef, ToFile, False, True);// Override record for workshop ref
  87.     ws := LinksTo(ElementByName(wscell, 'Worldspace'));
  88.     items := BP.A['items']; // Store the blueprint items array in items.
  89.     i := 0;
  90.     while i < items.Count do begin
  91.       obj := items.O[i];
  92.       pi := GetPluginIndex(obj.S['plugin_name']);
  93.       if pi = -1 then begin
  94.         AddMessage(obj.S['plugin_name'] + ' Plugin Not Found');
  95.       end
  96.       else begin
  97.         pos.x := StrToFloat(obj.S['posX']);
  98.         pos.y := StrToFloat(obj.S['posY']);
  99.         pos.z := StrToFloat(obj.S['posZ']);
  100.         c := wbPositionToGridCell(pos);
  101.         cell := GetCellFromWorldSpace(ws, c.x, c.y);
  102.         if Assigned(cell) then begin
  103.           form_id := IntToHex(GetLoadOrder(FileByIndex(pi)), 2) + obj.S['FormID'];
  104.           AddMasterIfMissing(ToFile, GetFileName(FileByIndex(pi)));
  105.           temp := wbCopyElementToFile(ElementByIndex(ChildGroup(cell), 0), ToFile, True, False);//cell -> temporary
  106.          
  107.           testPR := RecordByFormID(FileByIndex(pi), StrToInt64('$' + form_id), False);
  108.           if Signature(testPR) = 'NPC_' then reftype := 'ACHR' else reftype := 'REFR';
  109.          
  110.           ref := Add(temp, reftype, True);
  111.           SetElementEditValues(ref, 'NAME', form_id);
  112.           SetElementEditValues(ref, 'DATA\Position\X', obj.S['posX']);
  113.           SetElementEditValues(ref, 'DATA\Position\Y', obj.S['posY']);
  114.           SetElementEditValues(ref, 'DATA\Position\Z', obj.S['posZ']);
  115.           SetElementEditValues(ref, 'DATA\Rotation\X', obj.S['rotX']);
  116.           SetElementEditValues(ref, 'DATA\Rotation\Y', obj.S['rotY']);
  117.           SetElementEditValues(ref, 'DATA\Rotation\Z', obj.S['rotZ']);
  118.          
  119.           if obj.S['Scale'] <> '1.0' then begin
  120.             lr := Add(ref, 'XSCL', True);
  121.             if Assigned(lr) then
  122.               SetEditValue(lr, obj.S['Scale']);
  123.           end;
  124.          
  125.           lr := Add(ref, 'Linked References', True);
  126.           if Assigned(lr) then begin
  127.             SetElementEditValues(lr, 'XLKR\Keyword/Ref', '00054BA6');
  128.             SetElementEditValues(lr, 'XLKR\Ref', Name(workshopRef));
  129.           end;
  130.          
  131.           obj.I['RefId'] := GetLoadOrderFormID(ref);
  132.           obj.I['Cell'] := GetLoadOrderFormID(cell);
  133.         end;
  134.       end;
  135.       Inc(i);
  136.     end;
  137.    
  138.     // Start Powering Phase While
  139.     i := 0;
  140.     while i < items.Count do begin
  141.       obj := items.O[i];
  142.      
  143.       if obj.I['RefId'] <> 0 then
  144.         pi := GetPluginIndex(obj.S['plugin_name']);
  145.        
  146.         // Get Power Radiator
  147.         if not Assigned(powerRadiator) then begin
  148.           form_id := IntToHex(GetLoadOrder(FileByIndex(pi)), 2) + obj.S['FormID'];
  149.           testPR := RecordByFormID(FileByIndex(pi), StrToInt64('$' + form_id), False);
  150.           lr := ElementByPath(testPR, 'PRPS');
  151.           if Assigned(lr) then begin
  152.             sl := TStringList.Create;
  153.             j := 0;
  154.             while j < ElementCount(lr) do begin
  155.               sl.Add(GetElementEditValues(ElementByIndex(lr, j), 'Actor Value'));
  156.               Inc(j);
  157.             end;
  158.            
  159.             lr := ElementByPath(testPR, 'KWDA');
  160.             if Assigned(lr) then begin
  161.               j := 0;
  162.               while j < ElementCount(lr) do begin
  163.                 sl.Add(GetEditValue(ElementByIndex(lr, j)));
  164.                 Inc(j);
  165.               end;
  166.             end;
  167.            
  168.             if sl.IndexOf('PowerRadiation [AVIF:0000032F]') > -1 then
  169.               if sl.IndexOf('WorkshopSwitchActivatorKeyword [KYWD:001690A4]') = -1 then
  170.                 powerRadiator := RecordByFormID(ToFile, obj.I['RefId'], True);
  171.           end;
  172.         end;
  173.        
  174.         refA := RecordByFormID(ToFile, obj.I['RefId'], True);
  175.         cell := RecordByFormID(ToFile, obj.I['Cell'], True);
  176.        
  177.         // Start if Cables else Objects
  178.         // Start Cables
  179.         if obj.S['ConnectedObjects'] <> '' then begin
  180.          
  181.           sl := TStringList.Create;
  182.           SplitText(obj.S['ConnectedObjects'], sl);
  183.          
  184.           // Loop Connected Objects
  185.           j := 0;
  186.           while j < sl.Count do begin
  187.             // Start (Is Connected Object with greater Index)
  188.             if StrToInt(sl[j]) > i then begin
  189.               // Get Connected Object Ref
  190.               refB := RecordByFormID(ToFile, items.O[StrToInt(sl[j])].L['RefId'], True);
  191.              
  192.               // Create Spline
  193.               temp := wbCopyElementToFile(ElementByIndex(ChildGroup(cell), 0), ToFile, True, False);//cell -> temporary
  194.               ref := Add(temp, 'REFR', True);
  195.               SetElementEditValues(ref, 'NAME', '0001D971');
  196.               SetElementNativeValues(ref, 'DATA\Position\X', StrToFloat(obj.S['posX']) + ((GetElementNativeValues(refB, 'DATA\Position\X') - GetElementNativeValues(refA, 'DATA\Position\X'))/2));
  197.               SetElementNativeValues(ref, 'DATA\Position\Y', StrToFloat(obj.S['posY']) + ((GetElementNativeValues(refB, 'DATA\Position\Y') - GetElementNativeValues(refA, 'DATA\Position\Y'))/2));
  198.               SetElementNativeValues(ref, 'DATA\Position\Z', StrToFloat(obj.S['posZ']) + ((GetElementNativeValues(refB, 'DATA\Position\Z') - GetElementNativeValues(refA, 'DATA\Position\Z'))/2));
  199.               SetElementEditValues(ref, 'DATA\Rotation\X', '0.0');
  200.               SetElementEditValues(ref, 'DATA\Rotation\Y', '0.0');
  201.               SetElementEditValues(ref, 'DATA\Rotation\Z', '0.0');
  202.              
  203.               // Link Spline ref to workshop
  204.               lr := Add(ref, 'Linked References', True);
  205.               if Assigned(lr) then begin
  206.                 SetElementEditValues(lr, 'XLKR\Keyword/Ref', '00054BA6');
  207.                 SetElementEditValues(lr, 'XLKR\Ref', Name(workshopRefOverride));
  208.               end;
  209.              
  210.               // Set Spline Values
  211.               lr := Add(ref, 'XBSD', True);
  212.               if Assigned(lr) then begin
  213.                 // Slack
  214.                 SetEditValue(ElementByIndex(lr, 0), '0.051149');
  215.                 // Thickness
  216.                 SetEditValue(ElementByIndex(lr, 1), '1.500000');
  217.                 // ? Other point Relative X
  218.                 SetNativeValue(ElementByIndex(lr, 2), (GetElementNativeValues(refB, 'DATA\Position\X') - GetElementNativeValues(refA, 'DATA\Position\X'))/2);
  219.                 // ? Other point Relative Y
  220.                 SetNativeValue(ElementByIndex(lr, 3), (GetElementNativeValues(refB, 'DATA\Position\Y') - GetElementNativeValues(refA, 'DATA\Position\Y'))/2);
  221.                 // ? Other point Relative Z
  222.                 SetNativeValue(ElementByIndex(lr, 4), (GetElementNativeValues(refB, 'DATA\Position\Z') - GetElementNativeValues(refA, 'DATA\Position\Z'))/2);
  223.                 // Detached End
  224.                 SetEditValue(ElementByIndex(lr, 5), 'False');
  225.               end;
  226.              
  227.               // Set Spline Connections
  228.               AddOrAssign(ref, 'Spline Connection', 'Ref', Name(refA));
  229.               AddOrAssign(ref, 'Spline Connection', 'Ref', Name(refB));
  230.               AddOrAssign(refA, 'Spline Connection', 'Ref', Name(ref));
  231.               AddOrAssign(refB, 'Spline Connection', 'Ref', Name(ref));
  232.              
  233.               // Setup Grid
  234.               if ElementExists(workshopRefOverride, 'Power Grid') then begin
  235.                 lr := ElementByPath(workshopRefOverride, 'Power Grid');
  236.                 SetElementNativeValues(lr, 'XWPG', GetElementNativeValues(lr, 'XWPG') + 1);
  237.                 lr := ElementByPath(lr, 'Connections');
  238.                 if Assigned(lr) then begin
  239.                   lr := ElementAssign(lr, HighInteger, nil, False);
  240.                   if Assigned(lr) then begin
  241.                     SetElementEditValues(lr, 'Node 1', Name(refA));
  242.                     SetElementEditValues(lr, 'Node 2', Name(refB));
  243.                     SetElementEditValues(lr, 'Line', Name(ref));
  244.                   end;
  245.                 end;
  246.               end
  247.               else begin
  248.                 lr := Add(workshopRefOverride, 'Power Grid', True);
  249.                 if Assigned(lr) then begin
  250.                   SetElementEditValues(lr, 'XWPG', '1');
  251.                   lr := Add(lr, 'XWPN', False);
  252.                   if Assigned(lr) then begin
  253.                     //AddMessage('Signature: ' + Signature(lr));
  254.                     SetElementEditValues(lr, 'XWPN\Node 1', Name(refA));
  255.                     SetElementEditValues(lr, 'XWPN\Node 2', Name(refB));
  256.                     SetElementEditValues(lr, 'XWPN\Line', Name(ref));
  257.                   end;
  258.                 end;
  259.               end;
  260.            
  261.             // End (Is Connected Object with greater Index)
  262.             end;
  263.             Inc(j);
  264.           // End Loop Connected Objects
  265.           end;
  266.         // End Cables
  267.         end
  268.         // Start Objects
  269.         else begin
  270.           // Start If assigned radiator
  271.           if Assigned(powerRadiator) then begin
  272.             // Start if powered
  273.             if obj.I['isPowered'] = 1 then begin
  274.               // Start Setup Grid
  275.               // Start Exist
  276.               if ElementExists(workshopRefOverride, 'Power Grid') then begin
  277.                 lr := ElementByPath(workshopRefOverride, 'Power Grid');
  278.                 SetElementNativeValues(lr, 'XWPG', GetElementNativeValues(lr, 'XWPG') + 1);
  279.                 lr := ElementByPath(lr, 'Connections');
  280.                 if Assigned(lr) then begin
  281.                   lr := ElementAssign(lr, HighInteger, nil, False);
  282.                   if Assigned(lr) then begin
  283.                     SetElementEditValues(lr, 'Node 1', Name(refA));
  284.                     SetElementEditValues(lr, 'Node 2', Name(powerRadiator));
  285.                   end;
  286.                 end;
  287.               // End Exits
  288.               end
  289.               // Start Not Exist
  290.               else begin
  291.                 lr := Add(workshopRefOverride, 'Power Grid', True);
  292.                 if Assigned(lr) then begin
  293.                   SetElementEditValues(lr, 'XWPG', '1');
  294.                   lr := Add(lr, 'XWPN', False);
  295.                   if Assigned(lr) then begin
  296.                     SetElementEditValues(lr, 'XWPN\Node 1', Name(refA));
  297.                     SetElementEditValues(lr, 'XWPN\Node 2', Name(powerRadiator));
  298.                   end;
  299.                 end;
  300.               // End Not Exits
  301.               // End Setup Grid
  302.               end;
  303.             // End if powered
  304.             end;
  305.           // End If assigned radiator
  306.           end;
  307.         // End Objects
  308.         // End if Cables else Objects
  309.         end;
  310.       Inc(i);
  311.     // End Powering Phase While
  312.     end;
  313.   finally
  314.     BP.Free;
  315.   end;
  316. end;
  317.  
  318. // in the initialization it just shows a dialogue to enter the path of the blueprint
  319. // and calls BeginImport with the given path
  320. function Initialize: Integer;
  321. var
  322.   s: string;
  323.   f: IInterface;
  324. begin
  325.   s := InputBox('Import TS Blueprint to esp.', 'Blueprint Path:', 'TS/bp.json');
  326.   s := Trim(s);
  327.   if s <> '' then begin
  328.     if ResourceExists(s) then begin
  329.       f := AddNewFile; //Shows a dialog to create a new esp.
  330.       if f <> nil then BeginImport(s, f) else AddMessage('Invalid File Name.');
  331.     end
  332.     else AddMessage('File ' + s + ' could not be found in the Data folder.');
  333.   end
  334.   else AddMessage('You must eneter the path of the blueprint (relative to Data).');
  335.   Result := 1;
  336. end;
  337.  
  338. function GetCellFromWorldspace(Worldspace: IInterface; GridX, GridY: integer): IInterface;
  339. var
  340.   blockidx, subblockidx, cellidx: integer;
  341.   wrldgrup, block, subblock, cell: IInterface;
  342.   Grid, GridBlock, GridSubBlock: TwbGridCell;
  343.   LabelBlock, LabelSubBlock: Cardinal;
  344. begin
  345.   Grid := wbGridCell(GridX, GridY);
  346.   GridSubBlock := wbSubBlockFromGridCell(Grid);
  347.   LabelSubBlock := wbGridCellToGroupLabel(GridSubBlock);
  348.   GridBlock := wbBlockFromSubBlock(GridSubBlock);
  349.   LabelBlock := wbGridCellToGroupLabel(GridBlock);
  350.  
  351.   wrldgrup := ChildGroup(Worldspace);
  352.   // iterate over Exterior Blocks
  353.   for blockidx := 0 to Pred(ElementCount(wrldgrup)) do begin
  354.     block := ElementByIndex(wrldgrup, blockidx);
  355.     if GroupLabel(block) <> LabelBlock then Continue;
  356.     // iterate over SubBlocks
  357.     for subblockidx := 0 to Pred(ElementCount(block)) do begin
  358.       subblock := ElementByIndex(block, subblockidx);
  359.       if GroupLabel(subblock) <> LabelSubBlock then Continue;
  360.       // iterate over Cells
  361.       for cellidx := 0 to Pred(ElementCount(subblock)) do begin
  362.         cell := ElementByIndex(subblock, cellidx);
  363.         if (Signature(cell) <> 'CELL') or GetIsPersistent(cell) then Continue;
  364.         if (GetElementNativeValues(cell, 'XCLC\X') = Grid.x) and (GetElementNativeValues(cell, 'XCLC\Y') = Grid.y) then begin
  365.           Result := cell;
  366.           Exit;
  367.         end;
  368.       end;
  369.       Break;
  370.     end;
  371.     Break;
  372.   end;
  373. end;
  374.  
  375. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement