Skip to content

Instantly share code, notes, and snippets.

@theeternalsw0rd
Created May 26, 2025 05:12
Show Gist options
  • Save theeternalsw0rd/b0d5555884c7b8fc262ead244624faae to your computer and use it in GitHub Desktop.
Save theeternalsw0rd/b0d5555884c7b8fc262ead244624faae to your computer and use it in GitHub Desktop.
xEdit Script to Generate batch files that grant perks from perk trees
unit GeneratePerkTreeBatches;
uses
SysUtils, Classes;
// Script: GenerateAddTreePerksOrdered.pas
// Purpose: Generate a series of console bat files granting Skyrim perks in a perk tree in dependency order,
function Initialize: integer;
begin
Result := 0;
ForceDirectories(DataPath + 'Scripts');
end;
procedure ProcessAVIF(e: IInterface);
var
perkTree, element, perk: IInterface;
i, localID: Integer;
name, outPath: string;
output: TStringList;
begin
// AddMessage('Element is AVIF, check for perk tree'); // debug
perkTree := ElementByPath(e, 'Perk Tree');
if ElementCount(perkTree) > 0 then
// Perk Tree exists on record
begin
// store EDID of AVIF for future reference
output := TStringList.Create;
name := GetElementEditValues(e, 'EDID');
outPath := DataPath + 'Scripts\' + name + '.txt';
AddMessage('>> Initialize: output >> ' + outPath);
for i := 0 to Pred(ElementCount(perkTree)) do
begin
element := ElementByIndex(perkTree, i);
if Assigned(element) then
begin
perk := ElementByPath(element, 'PNAM');
if Assigned(perk) then
begin
localID := GetElementNativeValues(element, 'PNAM');
if localID <> 0 then
// filter out null reference included on every perk tree
begin
perk := LinksTo(perk);
repeat
// AddMessage(GeneratePerkString(perk)); // debug
output.Add(GeneratePerkString(perk));
perk := LinksTo(ElementByPath(perk, 'NNAM'));
until not Assigned(perk);
end;
end;
end;
end;
output.SaveToFile(outPath);
output.Free;
end;
end;
function Process(e: IInterface): integer;
begin
Result := 0;
if Signature(e) <> 'AVIF' then Exit;
ProcessAVIF(e);
end;
function GeneratePerkString(e: IInterface): string;
var
dispName, edid, pluginName: string;
begin
dispName := GetElementEditValues(e, 'FULL - Name');
edid := GetElementEditValues(e, 'EDID');
pluginName := GetFileName(GetFile(MasterOrSelf(e)));
Result :=
'player.addperk ' + IntToHex(GetLoadOrderFormID(e), 8)
+ '; ' + dispName + ' [' + edid + ']; ' + pluginName;
end;
function Finalize: integer;
begin
Result := 0;
end;
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment