Jump to content

Automation Tools for TES5Edit - Suggestions Thread


matortheeternal

Recommended Posts

JobVanDam,

 

I don't know if this would help but one way I indirectly do that is by using my export selection script. It exports records of all entries in your selection (whole mod, or specific sub categories). The trick is to open the file in something like NotePad++ and look at the line numbers, which should tell you how many items there are (remember to remove empty lines). The script below should export FormID + EditorID + Full Name, or you can tweak it to export other data.

 

Also, another way is to look at the system messages like:

[Apply Script done] Processed Records: 8, Elapsed Time: 00:00. <-- this mod has 8 records.

 

I'm sure there are other, simple or better ways that the experts here may tell you about ;P

 

{
Print records of a selection in any order, A-Z or Z-A.
By Rezel (Treplos) // ReverseSort Procedure by Zilav.
 
Hotkey: Ctrl+P
}
 
Unit Userscript;
 
var
  FName: string;
  slPrint: TStringList;
 
//===========================================================================
 
Function Initialize: Integer;
 
Begin
  slPrint := TStringList.Create;
  //slPrint.Sorted := True;
End;
 
//===========================================================================
 
Function Process(e: IInterface): Integer;
 
Begin
 
// -------------------------------------------
// Choose what data to print: comment out the line you don't want & uncomment the one you want.
// -------------------------------------------
 
// (1) FormID + EditorID + Full Name
slPrint.Add(IntToHex(FixedFormID(e), 8) + ' ; ' + GetElementEditValues(e, 'EDID') + ' ; ' + GetElementEditValues(e, 'FULL'));
 
// (2) FormID + EditorID
// slPrint.Add(IntToHex(FixedFormID(e), 8) + ' ; ' + GetElementEditValues(e, 'EDID'));
 
// (3) EditorID + Full Name
// slPrint.Add(GetElementEditValues(e, 'EDID') + ' ; ' + GetElementEditValues(e, 'FULL'));
 
// (4) Mod Name
// slPrint.Add(GetFileName(GetFile(e)));
 
// (5) EditorID
// slPrint.Add(GetElementEditValues(e, 'EDID'));
 
// (6) Full Name
// slPrint.Add(GetElementNativeValues(e, 'FULL'));
// slPrint.Add(GetElementEditValues(e, 'FULL'));
 
End;
 
//===========================================================================
 
Procedure ReverseSort(slPrint: TStringList);
 
var
  i: integer;
  s: string;
 
begin
  slPrint.Sort;
  for i := 0 to slPrint.Count div 2 - 1 do begin
    s := slPrint[i];
    slPrint[i] := slPrint[slPrint.Count-i-1];
    slPrint[slPrint.Count-i-1] := s;
  end;
end;
 
//===========================================================================
 
Function Finalize: Integer;
 
Begin
 
// -------------------------------------------
// Choose your sorting method
// -------------------------------------------
 
// Sort A-Z -->  Leave as default.
  slPrint.Sort;
 
// Sort Z-A -->  Uncomment to get reverse Z-A sorting.
  //ReverseSort(slPrint);
 
//FName := '%USERPROFILE%\My Documents\' + '-- Export.txt';
  FName := ProgramPath + '-- Export.txt';
  slPrint.SaveToFile(FName);
  AddMessage('>>> Saving list to ' + FName);
  slPrint.Free;
  Result := 1;
 
End;
 
End.

Edited by Treplos
Link to comment
Share on other sites

  • Replies 446
  • Created
  • Last Reply

Top Posters In This Topic

 

Is there anything that will automatically count all the items in any list so I don't have to?

Annoying sometimes to have count each item myself sometimes to ensure i enter the correct number of items in a list.

 

When you say "List" what do you mean?

  • StringLists in pascal code?
  • Arrays in pascal code?
  • Records in a group (with a signature) in TES5Edit?
  • Elements in a container in TES5Edit?
  • Records after filtering?

 

- M

 

Sorry, I was referring to the number of items in a leveled list or the numbers of items an NPC has etc.

 

Treplos

Thanks, I will try that script out and see how it goes.

 

 

Link to comment
Share on other sites

 

You have two thens at line "if Name(..."

It was a copy-paste mistake. Solved it.

I don't think it's a good idea to use Name for filenames. Use GetFileName()

 

Done

 

You don't need to store the copyfile as an IInterface object, you only need the file name, which should be a global string variable.

Sorry but I don't understand how. 'f' is IwbFile so 'copyfile' must be IwbFile too. Am I wrong?

 

Fix your indentation, please, it's difficult to read because it's all wrong.

Put an empty line between functions, this also helps with readability.

Done

And about troubleshooting. Looks like the only problem is with "Process" function. I don't get even "Start matching names" message. Here is my code now

unit userscript;

var
    s1, slPath: string;
    i: integer;
    f, ovrec, copyfile: IInterface;
 
function Initialize: integer;
begin
  // initialize your stuff here
  // use InputBox to accept user input for filename, then use a loop to find that file and store it in a variable.  I do this in several of my scripts.
  // use a looping InputBox until the input is empty to add paths the user wants to copy things from to a stringlist: slPaths
   s1 := InputBox('File','Enter the name of the file containing the record you want to copy an element from, including the file extension','Skyrim.esm');
      for i := 0 to FileCount - 1 do
        begin
            f:= FileByIndex(i);
            AddMessage('Checking file '+GetFileName(f));
            if SameText(s1, GetFileName(f)) then
                begin
                    copyfile := f;
                    AddMessage('File is '+GetFileName(copyfile));
                    Break;
                end;
        end;
slPath := InputBox('Path', 'Enter path you want to copy', '');
AddMessage('Path is '+slPath);
//here i have not array of pathes but only one. That's what i need
end;

function Process(e: IInterface): integer;
begin
    AddMessage('Start Process function');
    for i := 0 to OverrideCount(e) - 1 do
    begin
        AddMessage('Start matching names');
        if GetFileName(GetFile(OverrideByIndex(e, i))) = GetFileName(copyfile) then begin
            AddMessage('Names match');
            ovrec := OverrideByIndex(e, i);
            AddMessage('ovrec assigned: '+GetElementEditValues(ovrec, 'EDID'));
            Break;
        end;
    end;
    wbCopyElementToRecord(e, ElementByPath(ovrec, slPath), True, True);
    //changeg first boolean to False because it is referred as "aAsNew"... And what i need is to replace old record (weight or price), not to add something new.
    //doesn't work both with True of False anyway
end;
end.

I hope I don't bore you too much matortheeternal

I'm just really limited with my time, and this script is all I need to continue development of my mod (which I'm still intending to continue).

So I just have to hope that you consider helping me with it... And of course I'll understand if you don't want to bother with it.

Edited by DanielUA
Link to comment
Share on other sites

And about troubleshooting. Looks like the only problem is with "Process" function. I don't get even "Start matching names" message. Here is my code now

 

You're selecting several records, then right clicking, then applying the script? Process function only runs on selected records. If you are selecting records than that is odd, and I'll have to try it out myself to see what's going on.

 

 

unit userscript;

var
    s1, slPath: string;
    i: integer;
    f, ovrec, copyfile: IInterface;
 
function Initialize: integer;
begin
  // initialize your stuff here
  // use InputBox to accept user input for filename, then use a loop to find that file and store it in a variable.  I do this in several of my scripts.
  // use a looping InputBox until the input is empty to add paths the user wants to copy things from to a stringlist: slPaths
   s1 := InputBox('File','Enter the name of the file containing the record you want to copy an element from, including the file extension','Skyrim.esm');
      for i := 0 to FileCount - 1 do
        begin
            f:= FileByIndex(i);
            AddMessage('Checking file '+GetFileName(f));
            if SameText(s1, GetFileName(f)) then
                begin
                    copyfile := f;
                    AddMessage('File is '+GetFileName(copyfile));
                    Break;
                end;
        end;
slPath := InputBox('Path', 'Enter path you want to copy', '');
AddMessage('Path is '+slPath);
//here i have not array of pathes but only one. That's what i need
end;

function Process(e: IInterface): integer;
begin
    AddMessage('Start Process function');
    for i := 0 to OverrideCount(e) - 1 do
    begin
        AddMessage('Start matching names');
        if GetFileName(GetFile(OverrideByIndex(e, i))) = GetFileName(copyfile) then begin
            AddMessage('Names match');
            ovrec := OverrideByIndex(e, i);
            AddMessage('ovrec assigned: '+GetElementEditValues(ovrec, 'EDID'));
            Break;
        end;
    end;
    wbCopyElementToRecord(e, ElementByPath(ovrec, slPath), True, True);
    //changeg first boolean to False because it is referred as "aAsNew"... And what i need is to replace old record (weight or price), not to add something new.
    //doesn't work both with True of False anyway
end;
end.

 

I'll test out this code and let you know what I figure out.

 

 

I hope I don't bore you too much matortheeternal

 

Naw man, I'm happy to help. ;)

Sorry it took so long to respond, I was on a trip.

 

 

I'm just really limited with my time, and this script is all I need to continue development of my mod (which I'm still intending to continue).

So I just have to hope that you consider helping me with it... And of course I'll understand if you don't want to bother with it.

 

I'll see to it that you finish it.

 

 

Edit: it appears OverrideByIndex may be broken. Either that, or I'm using it wrong.

Edit 2: will do some more testing and stuff today. we could use RecordByFormID if we can't figure out why OverrideByIndex isn't working.

Edited by matortheeternal
Link to comment
Share on other sites

Looking forward to it :smile:

 

I think I figured it out. Silly me. I need to get the master record before I can use OverrideCount and OverrideByIndex. Those commands find the override records of a main/baserecord, so running them on an override record doesn't work. Silly me. I'll get to this later today.

Link to comment
Share on other sites

DanielUA: Script is working 100%.

 

 

unit userscript;

var
  s1, sPath: string;
  i: integer;
  f, ovRec, copyfile: IInterface;
 
function Initialize: integer;
begin
  // initialize your stuff here
  // use InputBox to accept user input for filename, then use a loop to find that file and store it in a variable.  I do this in several of my scripts.
  // use a looping InputBox until the input is empty to add paths the user wants to copy things from to a stringlist: sPaths
  s1 := InputBox('File','Enter the name of the file containing the record you want to copy an element from, including the file extension','Skyrim.esm');
  for i := 0 to FileCount - 1 do begin
    f := FileByIndex(i);
    AddMessage('Checking file '+GetFileName(f));
    if SameText(s1, GetFileName(f)) then begin
      copyfile := f;
      AddMessage('File is '+GetFileName(copyfile));
      Break;
    end;
  end;
  sPath := InputBox('Path', 'Enter path you want to copy', '');
  AddMessage('Path is '+sPath);
  //here i have not array of pathes but only one. That's what i need
end;

function Process(e: IInterface): integer;
var
  i: integer;
  mRec: IInterface;
begin
  AddMessage('Processing'+Name(e));
  mRec := MasterOrSelf(e);
  
  // skip if record is master (the script can only be run on override records)
  if Equals(mRec, e) then begin
    AddMessage('Selected record: '+Name(e)+' is a base record, skipping.');
    exit;
  end;
  
  // check if master record is the one user wanted to copy values from
  if GetFileName(GetFile(mRec)) = GetFileName(copyfile) then begin
    AddMessage('    Copying values from master record.');
    if not SameText(GetElementEditValues(e, sPath), '') then
      AddMessage('        Value at path: '+sPath+' changed from: '+GetElementEditValues(e, sPath)+' to: '+GetElementEditValues(mRec, sPath))
    else
      AddMessage('        Value at path: '+sPath+' restored.');
    wbCopyElementToRecord(ElementByPath(mRec, sPath), e, False, True);
  end
  else begin
    // look for a lower override to copy values from
    for i := 0 to OverrideCount(mRec) - 1 do begin
      AddMessage('    Looking for override record...');
      if GetFileName(GetFile(OverrideByIndex(mRec, i))) = GetFileName(copyfile) then begin
        AddMessage('    Found override record.');
        ovRec := OverrideByIndex(mRec, i);
        AddMessage('    ovRec assigned: '+GetElementEditValues(ovRec, 'EDID'));
        Break;
      end;
    end;
    if not SameText(GetElementEditValues(e, sPath), '') then
      AddMessage('        Value at path: '+sPath+' changed from: '+GetElementEditValues(e, sPath)+' to: '+GetElementEditValues(ovRec, sPath))
    else
      AddMessage('        Value at path: '+sPath+' restored.');
    wbCopyElementToRecord(ElementByPath(ovRec, sPath), e, False, True);
  end;
end;


end.

 

Edit: Incorporated into QuickChange. Will have a link to QuickChange v1.7 in a minute.

 

Edit 2: QuickChange v1.7. Right Click -> Save Link As.

Edited by matortheeternal
Link to comment
Share on other sites

mator, thank you!!! I'm really happy to finally have and use this script. Makes everything so much easier.

And immediately a bugreport :)

Everything worked perfect for me when I tried to copy DATA\Weight from Skyrim.esm to my esp.

But when I tried to copy it from another esp (Weapon and Armor fixes Remade) I had mistake:

"List index out of bounds (3)."

Link to comment
Share on other sites

mator, thank you!!! I'm really happy to finally have and use this script. Makes everything so much easier.

And immediately a bugreport :smile:

Everything worked perfect for me when I tried to copy DATA\Weight from Skyrim.esm to my esp.

But when I tried to copy it from another esp (Weapon and Armor fixes Remade) I had mistake:

"List index out of bounds (3)."

 

Hmm... 3 is way too high for OverrideByIndex. It should be more like 0, or something. I'll look into this.

Edited by matortheeternal
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...