Jump to content
  • 0

TES5Edit scripting - Slow function wbCopyElementToFile


MilletGtR

Question

Hi fellow modders, I'm MilletGtR, the creator of iActivate on the Nexus.

 

I've just recently gotten into the world of pascal scripting, so please forgive me if my quesions have obvious answers :) I'll get right into my issue.

 

In iActivate, I have altered some of the game setting strings to hide the Activate text, such as "Open", "Talk" and "Search". The problem there is that some items in the world of Skyrim have an "Activate Text Override" defined, meaning it overwrites the game setting (Open, Search, Talk and so on). Initially I had the ambition to edit all of these objects by hand, to be included in the mods .esp, but that took a stop when I realized that it would require patch after patch to be compatible with some of the more popular mods out there.

 

Instead I decided to learn Pascal and create a script in TES5Edit that people can run and make their own patch for their own load order. I've now created a fully functional script which finds all relevant records which contains the element 'RNAM' (which is the code for Activate Text Override), copies them to a new file, and at the same time removes the string attatched to 'RNAM'.

 

Now I've come to my issue: The script works very well on small .esp's, but the bigger the plugin file, the longer it takes per record copied. It seems to be exponential.

 

Down below is my complete script. Due to my research I suspect that the culprit is the wbCopyElementToFile function, which to me seems to scan the entire record every single time the procedure is run.

 

 

{
Creates a patch for iActivate that selects all relevant records containing the element 'RNAM' or
"Activate Text Override", and modifies them to remove the string that is defined in 'RNAM'.
}

unit UserScript;

var
iAFile: IInterface;
RNAMList: TStringList;
recs: array [0..50000] of IInterface;


function Initialize: integer;
var
    i: Integer;

begin
i := MessageDlg('Before running this script, you should be aware that:'+chr(13)+'1. You need to select all plugins that you wish to apply this script to, before running the script.'+chr(13)+'2. If you create this patch and later remove any of its master plugins you selected in step 1, you need delete the previously created patch, and create a new patch with this script, or the game will crash on startup.'+chr(13)+'3. This may take a while to process, so be patient.'+chr(13)+''+chr(13)+'Are you sure you wish to continue?', mtConfirmation, [mbYes, mbCancel], 0);
if i = mrYes then begin
    RNAMList := TStringList.Create;
    AddMessage('Building RNAM list, please stand by..');
end else begin
Result := 1;
Exit;
end;
end;


function Process(e: IInterface): integer;
var
ID: integer;
s: string;

begin
   
 //Ignores all signatures except the ones below.
if     (Signature(e) 'ACTI') and
    (Signature(e) 'CONT') and
    (Signature(e) 'FLOR') and
    (Signature(e) 'FURN') then
    Exit;
   
 //If the searched record does not contain the element 'RNAM', then skip record.
if not ElementExists(e, 'RNAM') then
Exit;
    
   
 //IntToHex converts the Value to a Hexadecimal string. IntToHex(Value, Digits) where Digits is the desired character length.
s := IntToHex(FormID(e), 8);
ID := RNAMList.IndexOf(s);
if ID = -1 then begin
recs[RNAMList.Count] := e;
RNAMList.Add(s);
    AddMessage('Copying ' + FullPath(e));

end else
recs[iD] := e;
end;


function Finalize: integer;
var
i: integer;
r, t: IInterface;

begin
if RNAMList.Count 0 then begin
   
 // Creates a new file where the above defined records will be stored.
    iAFile := AddNewFile;
if not Assigned(iAFile) then begin
AddMessage('Failed to create patch.');
Result := 1;
Exit;
end;
for i := 0 to RNAMList.Count - 1 do begin
r := recs;
    
// Adds the current plugin as a master file.
AddRequiredElementMasters(GetFile®, iAFile, False);

   
 // copy CELL record to patch, parameters: record, file, AsNew, DeepCopy
    t := wbCopyElementToFile(r, iAFile, False, True);
    SetElementEditValues(t, 'RNAM', '');

    AddMessage('Copied ' + FullPath®);
end;
AddMessage(Format('Patch file created with %d RNAM records.', [RNAMList.Count]));
end else
AddMessage('Script found no elements containing RNAM.');
RNAMList.Free;
end;

end.

 

If anyone has any idea as to why the script runs so slowly on big files, please reply with any information. I'm at the end of the rope, and can't figure this one out.

 

I should also mention that my script runs very well and rapidly in the Procedure function, but extremely slowly on the Finalize function.

 

Millet

Edited by MilletGtR
Link to comment
Share on other sites

Recommended Posts

  • 0

Thank you, but to be honest I did borrow a lot of snippets from other scripts, but tweaking them for my own purpose. Still it is very fun!

 

I do know about the scripting functions, as I've spent a lot of time there, but I didn't know you had to log in to access the changes/additions.. That would have been useful to know. I appreciate you telling me.

Link to comment
Share on other sites

  • 0

Glad I could be of help.  Let me know if you need any help with TES5Edit scripting in the future.  I'm happy to help.  :)

Having AddMessage is fine so long as it's not making your script unreasonably long to execute.  50 seconds for a full load order is very reasonable, so you don't have to worry about implementing a ProgressForm for additional performance.

 

Regarding ThreeTen's recommendation to forgo the Process function:
You could do this, but I personally feel its nice to have the Process function because it allows users to run the script on a select few mods to create a patch for just those mods.  As long as you provide clear instructions for general usage it shouldn't be an issue to your users.  I mean, heck, my Merge Plugins script is super complicated, and it's being used by all sorts of people all the time!

Link to comment
Share on other sites

  • 0

I understand both of your arguments, and after testing both extensively, I choose to do it Mators way. Just like Mator said, as long as you make clear instructions, there shouldn't be any problems for new users (I've even added a message box directing people towards the guide, in case they miss it). This coupled with the ability to exclude any master from the list is a big plus (which you simply can't when automatically processing all loaded mods).

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site, you agree to our Guidelines, Privacy Policy, and Terms of Use.