防具を服に変換するためのSSEEdit用スクリプトです。
Convert - Armor to Clothing.pas (pascal)
{
Comvert armor to clothing.
}
unit userscript;
var
validKeywords, invalidKeywords: TStringList;
function Initialize: integer;
begin
validKeywords := TStringList.Create;
validKeywords.Add('0006BBE8'); // ArmorHeavy
validKeywords.Add('0008F95B'); // VenderItemClothing
invalidKeywords := TStringList.Create;
invalidKeywords.Add('0006BBD2'); // ArmorHeavy
invalidKeywords.Add('0006BBD3'); // ArmorLight
invalidKeywords.Add('0006C0EC'); // ArmorCuirass
invalidKeywords.Add('0006C0ED'); // ArmorBoots
invalidKeywords.Add('0006C0EE'); // ArmorHelmet
invalidKeywords.Add('0006C0EF'); // ArmorGauntlets
invalidKeywords.Add('0006BBD4'); // ArmorMaterialDaedric
invalidKeywords.Add('0006BBD5'); // ArmorMaterialDragonplate
invalidKeywords.Add('0006BBD6'); // ArmorMaterialDragonscale
invalidKeywords.Add('0006BBD7'); // ArmorMaterialDwarven
invalidKeywords.Add('0006BBD8'); // ArmorMaterialEbony
invalidKeywords.Add('0006BBD9'); // ArmorMaterialElven
invalidKeywords.Add('0006BBDA'); // ArmorMaterialElvenGilded
invalidKeywords.Add('0006BBDB'); // ArmorMaterialLeather
invalidKeywords.Add('0006BBDC'); // ArmorMaterialGrass
invalidKeywords.Add('0006BBDD'); // ArmorMaterialHide
invalidKeywords.Add('0006BBDE'); // ArmorMaterialScaled
invalidKeywords.Add('0006BBDF'); // ArmorMaterialStudded
invalidKeywords.Add('0006BBE0'); // ArmorMaterialImperialLight
invalidKeywords.Add('0006BBE1'); // ArmorMaterialImperialStudded
invalidKeywords.Add('0006BBE2'); // ArmorMaterialImperialHeavy
invalidKeywords.Add('0006BBE3'); // ArmorMaterialIron
invalidKeywords.Add('0006BBE4'); // ArmorMaterialIronBanded
invalidKeywords.Add('0006BBE5'); // ArmorMaterialOrcish
invalidKeywords.Add('0006BBE6'); // ArmorMaterialSteel
invalidKeywords.Add('0006BBE7'); // ArmorMaterialSteelPlate
invalidKeywords.Add('010009BD'); // ArmorMaterialFalmer
invalidKeywords.Add('010009C0'); // ArmorMaterialBlades
invalidKeywords.Add('04024100'); // DLC2ArmorMaterialBonemoldLight
invalidKeywords.Add('04024101'); // DLC2ArmorMaterialBonemoldHeavy
invalidKeywords.Add('04024102'); // DLC2ArmorMaterialChitinLight
invalidKeywords.Add('04024103'); // DLC2ArmorMaterialChitinHeavy
invalidKeywords.Add('04024104'); // DLC2ArmorMaterialNordicLight
invalidKeywords.Add('04024105'); // DLC2ArmorMaterialNordicHeavy
invalidKeywords.Add('04024106'); // DLC2ArmorMaterialStalhrinHeavy
invalidKeywords.Add('04024107'); // DLC2ArmorMaterialStalhrinLight
invalidKeywords.Add('0008F959'); // VenderItemArmor
end;
{
mteFunctions
https://github.com/matortheeternal/mteFunctions/blob/master/LICENSE
}
{
ElementByIP:
Element by Indexed Path
This is a function to help with getting at elements that are inside
lists. It allows you to use an "indexed path" to get at these elements
that would otherwise be inaccessible without multiple lines of code.
Example usage:
element0 := ElementByIP(e, 'Conditions\[0]\CTDA - \Function');
element1 := ElementByIP(e, 'Conditions\[1]\CTDA - \Function');
}
function ElementByIP(e: IInterface; ip: string): IInterface;
var
i, index: integer;
path: TStringList;
begin
// replace forward slashes with backslashes
ip := StringReplace(ip, '/', '\', [rfReplaceAll]);
// prepare path stringlist delimited by backslashes
path := TStringList.Create;
path.Delimiter := '\';
path.StrictDelimiter := true;
path.DelimitedText := ip;
// traverse path
for i := 0 to Pred(path.count) do begin
if Pos('[', path[i]) > 0 then begin
index := StrToInt(GetTextIn(path[i], '[', ']'));
e := ElementByIndex(e, index);
end
else
e := ElementByPath(e, path[i]);
end;
// set result
Result := e;
end;
{
GetTextIn:
Returns a substring of @str between characters @open and @close.
Example usage:
s := 'Hello [test] world';
AddMessage(GetTextIn(s, '[', ']')); // prints 'test'
}
function GetTextIn(str: string; open, close: char): string;
var
i, openIndex: integer;
bOpen: boolean;
begin
Result := '';
bOpen := false;
for i := 1 to Length(str) do begin
if not bOpen and (GetChar(str, i) = open) then begin
openIndex := i;
bOpen := true;
end;
if bOpen and (GetChar(str, i) = close) then begin
Result := CopyFromTo(str, openIndex + 1, i - 1);
break;
end;
end;
end;
{
GetChar:
Gets a character in a string and returns it.
Example usage:
s := '1234';
AddMessage(GetChar(s, 3)); //'3'
}
function GetChar(const s: string; n: integer): char;
begin
Result := Copy(s, n, 1);
end;
{
CopyFromTo:
A copy function that allows you to copy from one position to another.
This function is a better copy function, in my opinion.
Example usage:
s := 'Hi. I'm a cool guy.';
s := CopyFromTo(s, Pos('a', s), Pos('g', s));
AddMessage(s); //'a cool g'
}
function CopyFromTo(s: string; p1: integer; p2: integer): string;
begin
Result := '';
if p1 > p2 then exit;
Result := Copy(s, p1, p2 - p1 + 1);
end;
function Process(e: IInterface): integer;
var
slotmask, i: integer;
kwd, kwda: IInterface;
id: string;
slKeywords: TStringList;
begin
// abort if this element is not an armor
if Signature(e) <> 'ARMO' then Exit;
// abort if this element is clothing
if GetElementNativeValues(e, 'BOD2\Armor Type') = 2 then Exit;
// change to clothing
SetElementNativeValues(e, 'BOD2\Armor Type', 2);
// get keywords
kwda := ElementBySignature(e, 'KWDA');
if not Assigned(kwda) then Exit;
// get valid keywords
slKeywords := TStringList.Create;
for i := Pred( ElementCount(kwda) ) downto 0 do begin
kwd := ElementByIndex(kwda, i);
id := IntToHex(GetNativeValue(kwd), 8);
// remove invalid keyword
if invalidKeywords.IndexOf(id) = -1 then begin
slKeywords.Add(id);
end else begin
AddMessage( 'remove ' + GetEditValue(kwd) + ' from ' + GetElementEditValues(e, 'FULL') );
end;
end;
// get slotmask
slotmask := GetElementNativeValues(e, 'BOD2\First Person Flags');
if slotmask and $4 <> 0 then begin
if slKeywords.IndexOf('000A8657') = -1 then slKeywords.Add('000A8657');
end;
if slotmask and $80 <> 0 then begin
if slKeywords.IndexOf('0010CD12') = -1 then slKeywords.Add('0010CD12');
end;
if slotmask and ($1 + $2) <> 0 then begin
if slKeywords.IndexOf('0010CD11') = -1 then slKeywords.Add('0010CD11');
end;
if slotmask and $1000 <> 0 then begin
if slKeywords.IndexOf('0010CD08') = -1 then slKeywords.Add('0010CD08');
end;
if slotmask and ($1 + $8) <> 0 then begin
if slKeywords.IndexOf('0010CD13') = -1 then slKeywords.Add('0010CD13');
end;
// add valid keywords
for i := 0 to validKeywords.Count - 1 do begin
if slKeywords.IndexOf(validKeywords[i]) = -1 then begin
slKeywords.Add(validKeywords[i]);
end;
end;
{
for i := 0 to slKeywords.Count - 1 do begin
AddMessage(slKeywords[i]);
end;
}
// remove keywords
RemoveElement(e, 'KWDA');
// rebuild keywords
if slKeywords.Count > 0 then begin
// first one
Add(e, 'KWDA', True);
SetEditValue(ElementByIP(e, 'KWDA\[0]'), slKeywords[0]);
// second one
kwda := ElementBySignature(e, 'KWDA');
for i := 1 to slKeywords.Count - 1 do begin
kwd := ElementAssign(kwda, HighInteger, nil, False);
SetEditValue(kwd, slKeywords[i]);
end;
// update keyword count
SetElementNativeValues(e, 'KSIZ', slKeywords.Count);
end else begin
// remove keyword count
RemoveElement(e, 'KSIZ');
end;
slKeywords.Free;
end;
function Finalize: integer;
begin
validKeywords.Free;
invalidKeywords.Free;
end;
end.