Talk:TES5Edit Scripting Functions

From the CreationKit Wiki
Jump to navigation Jump to search

Wiki Updates (for this page) don't seem to be updating for anyone who is not logged in. I've tried viewing the site on 3 different browsers and cleared my cache. It just doesn't want to update.

This has been a recurring issue with the wiki for a long time. For example, the site used to never show any SKSE function pages at all unless you were logged in. I'm not sure why it happens, or if that's still the case, because I've long since configured my browser to stay permanently logged in to this site. -egocarib (talk) 2015-05-25T11:18:16 (EDT)

TES5Edit Selection Detection[edit source]

Is there a way to tell during Initialize or Process if we have selected a single record, multiple records, or a plugin? I would like to know what the selection is before allowing Process to go anywhere. The TES4 form seems to always be the last so having Process kill itself on that wouldn't work well. --Darkconsole (talk) 2016-03-01T16:11:39 (EST)

Bugs[edit source]

As of TES5Edit 3.1.3 EXPERIMENTAL:

  • Working with overrides is broken in the following case and in any similar case. xEdit itself is capable of creating files that are broken in this manner, and the only solution is to totally delete them and find a way to start with non-broken files.
    • FileA.esp with Skyrim.esm and Update.esm as masters
    • FileB.esp with FileA.esp as its only master
      • This means that FileA forms have index 02 in xEdit's loaded file, but index 01 in FileB.
    • Call FormID(...) on any override in FileB
      • xEdit handles these overrides in a manner that is internally inconsistent: they will use load order prefix 02 in the UI and internally within the program, but xEdit APIs (e.g. Remove) called on them will use load order prefix 01, and the mismatch will cause these APIs to fail completely.
  • xEdit fails with an error if you call Remove or RemoveNode on an element that has previously been removed and reinserted into the file, either during the current attempt at executing a script or any prior attempt.
  • If you call AddElement on an element that is still in the hierarchy, then your script will fail with an executable-level assertion deep within xEdit's own code. Moreover, when xEdit closes, it will throw the same assertion, raising the question of whether the program itself is even safe to use after a script fails in this manner.

DavidJCobb (talk) 2017-05-04T05:23:59 (EDT)

Attempting to create a TStrings object throws an exception. Use TStringList instead. DavidJCobb (talk) 2017-05-07T21:42:28 (EDT)
Nested structures of the form TStringList<string, TStringList<string, IInterface>> will break ObjectToElement; the stored TObject will not be Nil, but accessing any fields on it will cause access violations, and calling ObjectToElement on it will return Nil. ObjectToElement cannot be trusted when working with nested lists. DavidJCobb (talk) 2017-05-22T20:00:53 (EDT)

Article rewrite[edit source]

Currently working to reorganize the list of scripting functions; saving my work under my userpage for now.

  • Explicitly describe the class-inheritance of data types that scripts are likely to encounter (e.g. a IwbMainRecord is an IwbContainer is an IwbElement)
  • Categorize functions by the internal data types they work with, instead of vomiting them all into a big pile that we can barely maintain
  • Pull function definitions from the source code, so that we aren't missing any functions (even if we don't know what they all do)
  • Use a template when listing functions on the page, to minimize ugly row markup and make it easier to style rows uniformly

Functions are made available to the scripting context through calls to AddFunction in wbScriptAdapter.pas. However, some scripting APIs wrap functions defined in other files, and it isn't always clear which other files they were defined in.

DavidJCobb (talk) 2017-05-05T17:55:49 (EDT)

Also, if anyone can find a free API/language reference for Delphi 5 (the 1999 one), we can go ahead and replace the entire "unsupported" section with a link to that, because that'll basically be the full list of what is supported (along with the xEdit extensions to the interpreter). That change would make the page and the scripting system itself look nicer. Thing is, I think the only official documentation was bundled with (purchases of) Delphi 5 itself, and it may not be *legal* to just pit that out there. Unofficial but comprehensive would be best. DavidJCobb (talk) 2017-05-06T06:49:39 (EDT)
Found the source code that JvInterpreter uses to provide the standard libraries. However, it's the current source code, not necessarily the source code for the version that xEdit uses. That means that we can't be sure that everything in these files is actually available.
One could in theory test each bit of functionality listed in that source code in an xEdit script, and construct documentation based on what works. However, that would basically be a language reference, and slamming an entire language reference (for a language Bethesda didn't create and doesn't maintain) into the main namespace of this wiki might not be a bad idea. The User namespace might be a better place for it. One could nest it under their userpage, and then use sub-pages and sub-sub-pages to describe things according to the class hierarchy, e.g. User:Someone/xEdit-Delphi/TListView/Items. At least, that's how I'd set it up if I had the time to undertake a project that massive.
If anyone else wants to burn time on it, the general setup for reading these source files is as follows:
  • APIs provided to scripts are defined in compiled code and receive two arguments: an out parameter, Value, and an Args argument of type TJvInterpreterArgs. The Value argument is the return value that will be sent back to the script. The Args argument has a Values property that contains the actual arguments that were received from the script, as variants; these will generally be cast to whatever the internal code actually wants, and that casting can be used to infer the desired argument type.
  • Elsewhere, typically at the bottom of the file, there will be a registrar function that passes these functions to JvInterpreter internal functions like AddClass, AddGet, AddSet, and AddFunction. Note that methods on classes are almost always registered via AddGet if they return a value, even if they aren't something you would be inclined to think of as a getter (e.g. the Create methods).
  • Those registration functions generally take these arguments: class or context to register the [gs]etter on; identifier (function/property name) seen by the script; function name; argument count; array of argument types; return value type. The varEmpty type appears to be used to represent all variants, unless it's simply a marker for "I don't require a strict type; I'll cast it anyway."
DavidJCobb (talk) 2017-05-07T03:25:51 (EDT)