new service files - updates to ll-stack-architecture.md

This commit is contained in:
2026-08-25 09:48:34 +02:00
parent 14f888843f
commit 6c8c89ffce
18 changed files with 644 additions and 34 deletions

View File

@@ -0,0 +1,270 @@
unit ExportScripts;
//version 1.0
// Global variables
var ArmoList : TStringList;
var ArmaList : TStringList;
var ArmoListSlot : TStringList;
var ArmaListSlot : TStringList;
var RetrieveAddRaces : Boolean;
// Called when the script starts
function Initialize : integer;
var
csvHeaderArmo: string;
csvHeaderArma: string;
begin
csvHeaderArma := 'Plugin;RecordType;FormID;EditorID;Slot;Race;MaleModel;FemaleModel;MaleModel1stPerson;FemaleModel1stPerson;AdditionalRaces';
csvHeaderArmo := 'Plugin;RecordType;FormID;EditorID;Slot;Race;Name;MaleModel;FemaleModel;Type;Enchantment;ArmorRating;Weight;Value;Keywords;ArmorAddon';
ArmoList := TStringList.Create;
ArmoList.Add(csvHeaderArmo);
ArmaList := TStringList.Create;
ArmaList.Add(csvHeaderArma);
ArmoListSlot := TStringList.Create;
ArmoListSlot.Add(csvHeaderArmo);
ArmaListSlot := TStringList.Create;
ArmaListSlot.Add(csvHeaderArma);
//don't retrieve 'Additional Races', takes too long
RetrieveAddRaces := False
end;
// Called for each selected record in the TES5Edit tree
function Process(e: IInterface): integer;
var
i: integer;
slot: cardinal;
espName: string;
recordType: string;
itemName: string;
maleModel: string;
femaleModel: string;
armorType: string;
nArmorType: integer;
typesList: array[0..2] of string;
enchantment: string;
rating: float;
weight: float;
value: integer;
maleModel1st: string;
femaleModel1st: string;
keywords: string;
armature: string;
elKwda: IInterface;
elArma: IInterface;
elRaces: IInterface;
slotList: TStringList;
formId: string;
primaryRace: string;
additionalRaces: string;
begin
if ((Signature(e) <> 'ARMO') and (Signature(e) <> 'ARMA')) then Exit;
typesList[0] := 'Light';
typesList[1] := 'Heavy';
typesList[2] := 'None';
slotList := TStringList.Create;
itemName := '';
armorType := '';
maleModel := '';
femaleModel := '';
enchantment := '';
maleModel1st := '';
femaleModel1st := '';
keywords := '';
rating := 0.0;
weight := 0.0;
value := 0.0;
formId := IntToHex(GetLoadOrderFormID(e), 8);
slotList.Delimiter := ',';
primaryRace := '';
espName := '[' + IntToStr(GetLoadOrder(GetFile(e))) + '] ' + GetFileName(e);
if ElementExists(e,'FULL') then itemName := GetElementEditValues(e, 'FULL');
if ElementExists(e,'EITM') then enchantment := GetElementEditValues(e, 'EITM');
if ElementExists(e,'DNAM') then rating := GetElementNativeValues(e, 'DNAM');
if ElementExists(e,'DATA\Value') then value := GetElementNativeValues(e, 'DATA\Value');
if ElementExists(e,'DATA\Weight') then weight := GetElementNativeValues(e, 'DATA\Weight');
if ElementExists(e,'RNAM') then primaryRace := GetElementEditValues(e, 'RNAM');
if ElementExists(e,'BODT\First Person Flags') then
begin
slot := GetElementNativeValues(e, 'BODT\First Person Flags');
if ElementExists(e,'BODT\Armor Type') then
begin
nArmorType := GetElementNativeValues(e, 'BODT\Armor Type');
armorType := typesList[nArmorType];
end
end
else
begin
if ElementExists(e,'BOD2\First Person Flags') then
begin
slot := GetElementNativeValues(e, 'BOD2\First Person Flags');
if ElementExists(e,'BOD2\Armor Type') then
begin
nArmorType := GetElementNativeValues(e, 'BOD2\Armor Type');
armorType := typesList[nArmorType];
end
end
else
begin
AddMessage('********* element doesnt have slot definition *********');
Exit;
end
end;
if Signature(e) = 'ARMA' then
begin
if ElementExists(e,'Male world model\MOD2') then maleModel := GetElementNativeValues(e, 'Male world model\MOD2');
if ElementExists(e,'Female world model\MOD3') then femaleModel := GetElementNativeValues(e, 'Female world model\MOD3');
if ElementExists(e,'Male 1st Person\MOD4') then maleModel1st := GetElementNativeValues(e, 'Male 1st Person\MOD4');
if ElementExists(e,'Female 1st Person\MOD5') then femaleModel1st := GetElementNativeValues(e, 'Female 1st Person\MOD5');
if RetrieveAddRaces and ElementExists(e,'Additional Races') then
begin
elRaces := ElementByName(e, 'Additional Races');
for i := 0 to ElementCount(elRaces) - 1 do begin
additionalRaces := additionalRaces + GetElementEditValues(LinksTo(ElementByIndex(elRaces,i)), 'EDID');
if(i < (ElementCount(elRaces) - 1)) then additionalRaces := additionalRaces + ',';
end;
end;
end
else
begin
if Signature(e) = 'ARMO' then
begin
if ElementExists(e,'Male world model\MOD2') then maleModel := GetElementNativeValues(e, 'Male world model\MOD2');
if ElementExists(e,'Female world model\MOD4') then femaleModel := GetElementNativeValues(e, 'Female world model\MOD4');
if ElementExists(e,'KWDA') then
begin
elKwda := ElementBySignature(e, 'KWDA');
for i := 0 to ElementCount(elKwda) - 1 do begin
keywords := keywords + GetElementEditValues(LinksTo(ElementByIndex(elKwda,i)), 'EDID');
if(i < (ElementCount(elKwda) - 1)) then keywords := keywords + ',';
end;
end;
if ElementExists(e,'Armature') then
begin
elArma := ElementByName(e, 'Armature');
for i := 0 to ElementCount(elArma) - 1 do begin
armature := armature + GetElementEditValues(LinksTo(ElementByIndex(elArma,i)), 'EDID');
if(i < (ElementCount(elArma) - 1)) then armature := armature + ',';
end;
end;
end
end;
//loop through the 32 slots
i := 1;
while(i <= 32) do
begin
i := i + 1;
//bitwise and
if ((slot and 1) = 1) then
begin
slotList.Add(IntToStr(i+28));
AddMessage(espName + ';' + Signature(e) + ';' + formId +';'+ GetElementEditValues(e, 'EDID') + ';' + itemName + ';' + maleModel + ';' + femaleModel +';' + armorType +';' + enchantment + ';' + FloatToStr(rating/100) + ';' + FloatToStr(weight) + ';' + IntToStr(value) + ';' + IntToStr(i+28) + ';' + keywords);
if Signature(e) = 'ARMO' then
ArmoListSlot.Add(espName + ';'
+ Signature(e) + ';'
+ formId + ';'
+ GetElementEditValues(e, 'EDID') + ';'
+ IntToStr(i+28) + ';'
+ primaryRace + ';'
+ itemName + ';'
+ maleModel + ';'
+ femaleModel +';'
+ armorType +';'
+ enchantment + ';'
+ FloatToStr(rating/100) + ';'
+ FloatToStr(weight) + ';'
+ IntToStr(value) + ';'
+ keywords + ';'
+ armature
);
if Signature(e) = 'ARMA' then
ArmaListSlot.Add(espName + ';'
+ Signature(e) + ';'
+ formId + ';'
+ GetElementEditValues(e, 'EDID') + ';'
+ IntToStr(i+28) + ';'
+ primaryRace + ';'
+ maleModel + ';'
+ femaleModel +';'
+ maleModel1st + ';'
+ femaleModel1st + ';'
+ additionalRaces
);
end
slot := slot shr 1;
end;
if Signature(e) = 'ARMO' then
ArmoList.Add(espName + ';'
+ Signature(e) + ';'
+ formId + ';'
+ GetElementEditValues(e, 'EDID') + ';'
+ slotList.DelimitedText + ';'
+ primaryRace + ';'
+ itemName + ';'
+ maleModel + ';'
+ femaleModel +';'
+ armorType +';'
+ enchantment + ';'
+ FloatToStr(rating/100) + ';'
+ FloatToStr(weight) + ';'
+ IntToStr(value) + ';'
+ keywords + ';'
+ armature
);
if Signature(e) = 'ARMA' then
ArmaList.Add(espName + ';'
+ Signature(e) + ';'
+ formId + ';'
+ GetElementEditValues(e, 'EDID') + ';'
+ slotList.DelimitedText + ';'
+ primaryRace + ';'
+ maleModel + ';'
+ femaleModel +';'
+ maleModel1st + ';'
+ femaleModel1st + ';'
+ additionalRaces
);
slotList.Free;
end;
// Called after the script has finished processing every record
function Finalize : integer;
var filenameArmo : string;
var filenameArma : string;
var filenameArmoSlot : string;
var filenameArmaSlot : string;
begin
filenameArmo := ProgramPath + 'ArmorExport-Armor.csv';
filenameArma := ProgramPath + 'ArmorExport-ArmorAddon.csv';
filenameArmoSlot := ProgramPath + 'ArmorExport-Armor-Slot.csv';
filenameArmaSlot := ProgramPath + 'ArmorExport-ArmorAddon-Slot.csv';
AddMessage('Saving Armor list to ' + filenameArmo);
AddMessage('Saving ArmorAddon list to ' + filenameArma);
AddMessage('Saving Armor-Slot list to ' + filenameArmoSlot);
AddMessage('Saving ArmorAddon-Slot list to ' + filenameArmaSlot);
ArmoList.SaveToFile(filenameArmo);
ArmoList.Free;
ArmaList.SaveToFile(filenameArma);
ArmaList.Free;
ArmoListSlot.SaveToFile(filenameArmoSlot);
ArmoListSlot.Free;
ArmaListSlot.SaveToFile(filenameArmaSlot);
ArmaListSlot.Free;
end;
end.

View File

@@ -0,0 +1,6 @@
param([Parameter(Mandatory=$true)][string[]]$keyword)
### keyword to filter
$csvDir=(Join-Path $PSScriptRoot ..)
Get-Content $csvDir\ArmorExport-Armor.csv|convertFrom-Csv -Delimiter ';' `
|ForEach-Object { $_.Keywords = ($_.Keywords -split ','); $_ } `
|where-object { $keyword -in $_.Keywords }

View File

@@ -0,0 +1,4 @@
param([Parameter(Mandatory=$true)][int]$slot)
#slot to filter
$csvDir=(Join-Path $PSScriptRoot ..)
Get-Content $csvDir\ArmorExport-Armor-Slot.csv|ConvertFrom-Csv -Delimiter ';'|Sort-Object -Property FormID,Slot -Unique|Where-Object { $_.Slot -eq $slot }

View File

@@ -0,0 +1,2 @@
$csvDir=(Join-Path $PSScriptRoot ..)
Get-Content $csvDir\ArmorExport-Armor.csv|convertFrom-Csv -Delimiter ';'|ForEach-Object { $_.Keywords = ($_.Keywords -split ','); $_ }|where-object { $_.Keywords -contains 'ArmorHeavy' }

View File

@@ -0,0 +1,2 @@
$csvDir=(Join-Path $PSScriptRoot ..)
Get-Content $csvDir\ArmorExport-Armor.csv|convertFrom-Csv -Delimiter ';'|ForEach-Object { $_.Keywords = ($_.Keywords -split ','); $_ }|where-object { $_.Keywords -contains 'ArmorLight' }

View File

@@ -0,0 +1,3 @@
#show count of records by slot
$csvDir=(Join-Path $PSScriptRoot ..)
Get-Content $csvDir\ArmorExport-Armor-Slot.csv|ConvertFrom-Csv -Delimiter ';'|Sort-Object -Property FormID,Slot -Unique|Sort-Object Slot|Group-Object -NoElement -Property slot

View File

@@ -0,0 +1,3 @@
param([Parameter(Mandatory=$true)][int]$slot)
$csvDir=(Join-Path $PSScriptRoot ..)
Get-Content $csvDir\ArmorExport-ArmorAddon-Slot.csv|ConvertFrom-Csv -Delimiter ';'|Sort-Object -Property FormID,Slot -Unique|Where-Object { $_.Slot -eq $slot }

View File

@@ -0,0 +1,3 @@
#show count of records by slot
$csvDir=(Join-Path $PSScriptRoot ..)
Get-Content $csvDir\ArmorExport-ArmorAddon-Slot.csv|ConvertFrom-Csv -Delimiter ';'|Sort-Object -Property FormID,Slot -Unique|Sort-Object Slot|Group-Object -NoElement -Property slot

View File

@@ -0,0 +1,51 @@
<#
.PARAMETER editorId
to filter by editorId
.PARAMETER formId
to filter by formId
.PARAMETER all
to list all records
.PARAMETER slotAsArray
convert slot field to array
.PARAMETER splitBySlot
split records by slot
.EXAMPLE
PS> .\get-armor.ps1 -editorId EnchArmorImperialLightGauntletsMarksman03
.EXAMPLE
PS> .\get-armor.ps1 -formId 000B9745
#>
param([string]$editorId, [string]$formId, [switch]$slotAsArray, [switch]$splitBySlot)
#editorId or formId to filter
#usage:
## .\get-armor.ps1 -editorId EnchArmorImperialLightGauntletsMarksman03
## .\get-armor.ps1 -formId 000B9745
$csvDir=(Join-Path $PSScriptRoot ..)
$csvFile="ArmorExport-Armor.csv"
if($splitBySlot) {
$csvFile="ArmorExport-Armor-Slot.csv"
}
if($editorId -or $formId) {
Get-Content (Join-Path $csvDir $csvFile)|ConvertFrom-Csv -Delimiter ';' `
|where-object { ($editorId -and $_.EditorID -eq $editorId) -or ($formId -and $_.FormID -eq $formId)} `
|foreach-object {
$_.Keywords = $_.Keywords -Split ',';
$_.ArmorAddon = $_.ArmorAddon -Split ',';
if($slotAsArray -and !$splitBySlot) { $_.Slot = ($_.Slot -Split ','); }
$_
}
} else {
Get-Content (Join-Path $csvDir $csvFile)|ConvertFrom-Csv -Delimiter ';' `
|foreach-object {
$_.Keywords = $_.Keywords -Split ',';
$_.ArmorAddon = $_.ArmorAddon -Split ',';
if($slotAsArray -and !$splitBySlot) { $_.Slot = ($_.Slot -Split ','); }
$_
}
}

View File

@@ -0,0 +1,88 @@
<#
.PARAMETER editorId
to filter by editorId
.PARAMETER formId
to filter by formId
.PARAMETER all
to list all records
.PARAMETER slotAsArray
convert slot field to array
.PARAMETER splitBySlot
split records by slot
.EXAMPLE
PS> .\get-armor.ps1 | ?{ $_.FormID -in '00013939' } | .\get-armoraddon.ps1
.EXAMPLE
PS> .\get-armoraddon.ps1 -formId 0005DB82
.EXAMPLE
PS> .\get-armor.ps1 -editorId EnchArmorImperialLightGauntletsMarksman03|.\get-armoraddon.ps1
.EXAMPLE
PS> .\armor-by-keyword.ps1 ArmorHeavy|?{$_.Keywords -contains 'ArmorHelmet'}|.\get-armoraddon.ps1
#>
param([string]$editorId, [string]$formId, [switch]$all, [switch]$slotAsArray, [switch]$splitBySlot)
# editorId or formId to filter
# -all to list all records
#usage:
## .\get-armor.ps1 | ?{ $_.FormID -in '00013939' } | .\get-armoraddon.ps1
## .\get-armoraddon.ps1 -formId 0005DB82
## .\get-armor.ps1 -editorId EnchArmorImperialLightGauntletsMarksman03|.\get-armoraddon.ps1
## .\armor-by-keyword.ps1 ArmorHeavy|?{$_.Keywords -contains 'ArmorHelmet'}|.\get-armoraddon.ps1
Set-StrictMode -Version 3.0
$csvDir=(Join-Path $PSScriptRoot ..)
$myInput = $input
$ids=@()
$inObjs=@{}
foreach($i in $myInput) {
foreach($a in $i.ArmorAddon) {
$ids+=$a;
if($inObjs.ContainsKey($a)) {
$inObjs[$a]=$i
} else {
$inObjs.Add($a, $i)
}
}
}
$csvDir=(Join-Path $PSScriptRoot ..)
$csvFile="ArmorExport-ArmorAddon.csv"
if($splitBySlot) {
$csvFile="ArmorExport-ArmorAddon-Slot.csv"
}
if($editorId -or $formId) {
Get-Content (Join-Path $csvDir $csvFile)|ConvertFrom-Csv -Delimiter ';' `
|where-object { ($editorId -and $_.EditorID -eq $editorId) -or ($formId -and $_.FormID -eq $formId)} `
|foreach-object { `
if($slotAsArray -and !$splitBySlot) { $_.Slot = ($_.Slot -Split ','); } `
$_.AdditionalRaces = ($_.AdditionalRaces -Split ','); `
$_ `
}
} elseif($ids.Length -gt 0) {
Get-Content (Join-Path $csvDir $csvFile)|ConvertFrom-Csv -Delimiter ';' `
|where-object { $ids -contains $_.EditorID } `
|foreach-object { `
if($slotAsArray -and !$splitBySlot) { $_.Slot = ($_.Slot -Split ','); } `
$_.AdditionalRaces = ($_.AdditionalRaces -Split ','); `
$_ } `
|foreach-object { Add-Member -InputObject $_ -MemberType NoteProperty -Name _ArmoRef `
-Value "$($inObjs[$_.EditorID].EditorID) `"$($inObjs[$_.EditorID].Name)`" [$($inObjs[$_.EditorID].RecordType):$($inObjs[$_.EditorID].FormID)]"; `
$_ }
} elseif($all) {
Get-Content (Join-Path $csvDir $csvFile)|ConvertFrom-Csv -Delimiter ';' `
|foreach-object { `
if($slotAsArray -and !$splitBySlot) { $_.Slot = ($_.Slot -Split ','); } `
$_.AdditionalRaces = ($_.AdditionalRaces -Split ','); `
$_ }
}