Skip to content

Instantly share code, notes, and snippets.

@yggdrasil75
Last active July 12, 2021 12:40
Show Gist options
  • Select an option

  • Save yggdrasil75/f54c9b2653e29e2a34578b55df94d352 to your computer and use it in GitHub Desktop.

Select an option

Save yggdrasil75/f54c9b2653e29e2a34578b55df94d352 to your computer and use it in GitHub Desktop.
unit CustomFunctionList;
{
```pascal
```
}
{ General Notes
If the code says it expects 'end;' but finds 'end of file' check that 'if' statements are followed by 'then' and 'for' statement are followed by 'do'
}
var
slGlobal, slProcessTime, TemplateMegaListvar: TStringList;
selectedRecord : IInterface;
Recipes, MaterialList, TempPerkListExtra: TStringList;
Ini,IniFileStreams : TMemIniFile;
HashedList, HashedTemperList : THashedStringList;
ignoreEmpty, disallowNP: boolean;
DisKeyword, disWord,BOD2List,Megalist : TStringList;
modifiers:TStringList;
defaultOutputPlugin : string;
defaultGenerateEnchantedVersions, defaultReplaceInLeveledList, defaultAllowDisenchanting, ProcessTime : boolean;
defaultBreakdownEnchanted, defaultBreakdownDaedric, defaultBreakdownDLC, defaultGenerateRecipes, Constant : boolean;
defaultChanceBoolean, defaultAutoDetect, defaultBreakdown, defaultOutfitSet, defaultCrafting, defaultTemper: boolean;
defaultChanceMultiplier, defaultEnchMultiplier, defaultItemTier01, defaultItemTier02, defaultItemTier03 : integer;
defaultItemTier04, defaultItemTier05, defaultItemTier06, defaultTemperLight, defaultTemperHeavy : integer;
firstRun : boolean;
/// ///////////////////////////// FILE BY NAME IS NATIVE PAST xEdit 4.1.x //////////////////////////////////
// Find loaded plugin by name
function FileByName(aPluginName: string): IInterface;
var
i: Integer;
begin
for i := 0 to Pred(FileCount) do begin
Result := FileByIndex(i);
if SameText(GetFileName(Result), aPluginName) then
Exit;
end;
Result := nil;
end;
/// ///////////////////////////// FILE BY NAME IS NATIVE PAST xEdit 4.1.x //////////////////////////////////
// Find loaded plugin by name (if it exists)
function doesFileExist(aPluginName: string): boolean;
var
i: Integer;
a: IInterface;
begin
result := false;
for i := 0 to Pred(FileCount) do begin
a := FileByIndex(i);
if SameText(GetFileName(a), aPluginName) then
begin
result := true;
Exit;
end;
end;
end;
// Removes records dependent on a specified master
procedure RemoveMastersAuto(inputPlugin, outputPlugin: IInterface);
var
slTemp, slRemove : TStringList;
tempRecord, tempelement: IInterface;
tempString : string;
debugMsg : boolean;
i, x, y : integer;
begin
// Begin debugMsg section
debugMsg := false;
// Initialize
{ Debug } if debugMsg then
addMessage('[RemoveMastersAuto] RemoveMastersAuto( ' + GetFileName(inputPlugin) + ', ' + GetFileName(outputPlugin) + ' )');
slTemp := TStringList.Create;
slRemove := TStringList.Create;
tempString := GetFileName(inputPlugin);
// Work
{ Debug } if debugMsg then
addMessage('[RemoveMastersAuto] for i := 0 to ' + IntToStr(Pred(ElementCount(outputPlugin))) + ' do begin');
for i := ElementCount(outputPlugin) - 1 downto 0 do
begin
tempelement := elementbyindex(outputPlugin, i);
{ Debug } if debugMsg then
addMessage('[RemoveMastersAuto] for x := 0 to ' + IntToStr(Pred(ElementCount(tempelement))) + ' do begin');
for x := ElementCount(tempelement) - 1 downto 0 do
begin
tempRecord := elementbyindex(tempelement, x);
ReportRequiredMasters(tempRecord, slTemp, false, true);
{ Debug } if debugMsg then
msgList('[RemoveMastersAuto] slTemp := ', slTemp, '');
for y := slTemp.Count - 1 downto 0 do
begin
{ Debug } if debugMsg then
addMessage('[RemoveMastersAuto] if ( ' + slTemp[y] + ' = ' + tempString + ' ) then begin');
if slTemp[y] = tempString then
begin
slRemove.addObject(EditorID(tempRecord), tempRecord);
break;
end;
end;
end;
end;
// Remove records
for i := slRemove.Count - 1 downto 0 do
begin
{ Debug } if debugMsg then
addMessage('[RemoveMastersAuto] Remove( ' + slRemove[i] + ' );');
Remove(ObjectToElement(slRemove.Objects[i]));
end;
// Finalize
slTemp.clear;
slRemove.clear;
debugMsg := false;
// End debugMsg section
end;
// Find where the selected record is referenced in leveled lists and make a 'Copy as Override' into a specified file. Then replace all instances of inputRecord with replaceRecord in the override
procedure ReplaceInLeveledListAuto(inputRecord, replaceRecord, aPlugin: IInterface);
var
LLrecord, LLcopy, masterRecord : IInterface;
debugMsg, patchBool : boolean;
startTime, stopTime : TDateTime;
tempString, patchFileName, LLrecord_EditorID, LLrecord_Sig: string;
i, x : integer;
begin
// Initialize
debugMsg := false;
startTime := Time;
{ Debug } if debugMsg then
addMessage('[ReplaceInLeveledListAuto] ReplaceInLeveledListAuto(' + EditorID(inputRecord) + ' with ' + EditorID(replaceRecord) + ' in ' + GetFileName(aPlugin) + ' );');
patchBool := slContains(slGlobal, 'Patch');
if patchBool then
patchFileName := GetFileName(ObjectToElement(GetObject('Patch', slGlobal)));
masterRecord := MasterOrSelf(inputRecord);
for i := ReferencedByCount(masterRecord) - 1 downto 0 do
begin
LLrecord := ReferencedByIndex(masterRecord, i);
LLrecord_EditorID := EditorID(LLrecord);
// records to skip
if patchBool then
if (GetFileName(GetFile(LLrecord)) <> patchFileName) then
Continue;
if not SameText(Signature(LLrecord), 'LVLI') then
Continue;
if SameText(LLrecord_EditorID, EditorID(replaceRecord)) then
Continue;
if ContainsText(LLrecord_EditorID, '++') or not IsHighestOverride(LLrecord, GetLoadOrder(aPlugin)) or (GetLoadOrder(GetFile(LLrecord)) > GetLoadOrder(aPlugin)) or (Length(LLrecord_EditorID) = 0) or FlagCheck(LLrecord, 'Special Loot') then
Continue;
if slContains(slGlobal, LLrecord_EditorID) then
if (EditorID(masterRecord) = EditorID(ObjectToElement(slGlobal.Objects[slGlobal.IndexOf(LLrecord_EditorID)]))) then
Continue;
if LLcontains(LLrecord, masterRecord) then
begin
LLcopy := MainRecordByEditorID(GroupBySignature(aPlugin, 'LVLI'), LLrecord_EditorID);
if not Assigned(LLcopy) then
LLcopy := wbCopyElementToFile(LLrecord, aPlugin, false, true);
{ Debug } if debugMsg then
addMessage('[ReplaceInLeveledListAuto] LLcopy := ' + EditorID(LLcopy));
if Assigned(LLcopy) then
begin
{ Debug } if debugMsg then
addMessage('[ReplaceInLeveledListAuto] LLreplace(' + EditorID(LLcopy) + ', ' + EditorID(masterRecord) + ', ' + EditorID(replaceRecord) + ' );');
while LLcontains(LLcopy, masterRecord) do
LLreplace(LLcopy, masterRecord, replaceRecord);
end;
end;
end;
// Finalize
stopTime := Time;
if ProcessTime then
addProcessTime('ReplaceInLeveledListAuto', TimeBtwn(startTime, stopTime));
end;
// Find where the selected record is referenced in leveled lists and make a 'Copy as Override' into a specified file. Then replace all instances of inputRecord with replaceRecord in the override
procedure ReplaceInLeveledListByList(aList, bList: TStringList; aPlugin: IInterface);
var
LLrecord, LLcopy, tempRecord, tempelement: IInterface;
i, x, y, tempInteger, LoadOrder : integer;
debugMsg, tempBoolean, patchBool : boolean;
startTime, stopTime : TDateTime;
slTemp, slLL : TStringList;
LLrecord_EditorID, patchFileName : string;
begin
// Initialize
debugMsg := false;
if ProcessTime then
startTime := Time;
{ Debug } if debugMsg then
addMessage('[ReplaceInLeveledListByList] ReplaceInLeveledListByList(aList, bList, ' + GetFileName(aPlugin) + ' );');
slTemp := TStringList.Create;
slLL := TStringList.Create;
// For the 'Patch' function
patchBool := slContains(slGlobal, 'Patch');
if patchBool then
patchFileName := GetFileName(ObjectToElement(GetObject('Patch', slGlobal)));
// main work 1
LoadOrder := GetLoadOrder(aPlugin);
for i := aList.Count - 1 downto 0 do
begin
tempRecord := ObjectToElement(aList.Objects[i]);
for x := ReferencedByCount(tempRecord) - 1 downto 0 do
begin
LLrecord := ReferencedByIndex(tempRecord, x);
LLrecord_EditorID := EditorID(LLrecord);
if not(Signature(LLrecord) = 'LVLI') then
Continue;
// single mode
if (GetFileName(GetFile(LLrecord)) <> patchFileName) then
Continue;
// Filter Invalid Entries
{ Debug } if debugMsg then
addMessage('[ReplaceInLeveledListByList] LLrecord := ' + LLrecord_EditorID);
if slContains(slLL, LLrecord_EditorID) then
Continue;
if ContainsText(LLrecord_EditorID, '++') or not(Length(LLrecord_EditorID) > 0) or not IsHighestOverride(LLrecord, GetLoadOrder(aPlugin)) or FlagCheck(LLrecord, 'Special Loot') then
Continue;
if slContains(slGlobal, LLrecord_EditorID) then
if not(EditorID(tempRecord) = EditorID(ObjectToElement(slGlobal.Objects[slGlobal.IndexOf(LLrecord_EditorID)]))) then
Continue;
if (LoadOrder <= GetLoadOrder(GetFile(LLrecord))) then
begin
if PreviousOverrideExists(LLrecord, LoadOrder) then
begin
LLrecord := GetPreviousOverride(LLrecord, LoadOrder);
end
else
Continue;
end
else
if debugMsg then
addMessage('[ReplaceInLeveledListByList] ' + LLrecord_EditorID + ' := ' + IntToStr(LoadOrder) + ' >= ' + IntToStr(GetLoadOrder(GetFile(LLrecord))));
// Add Copy to List
slLL.addObject(LLrecord_EditorID, LLrecord);
end;
end;
{ Debug } if debugMsg then
msgList('[ReplaceInLeveledListByList] slLL := ', slLL, ' );');
{ Debug } if debugMsg then
addMessage(' ');
// work 2
for i := slLL.Count - 1 downto 0 do
begin
LLrecord := ObjectToElement(slLL.Objects[i]);
LLrecord_EditorID := slLL[i];
{ Debug } if debugMsg then
addMessage('[ReplaceInLeveledListByList] LLrecord := ' + LLrecord_EditorID);
if not(Length(LLrecord_EditorID) > 0) then
Continue;
tempelement := ElementByName(LLrecord, 'Leveled List Entries');
for x := LLec(LLrecord) - 1 downto 0 do
begin
tempRecord := elementbyindex(tempelement, x);
slTemp.addObject(StrPosCopy(GetElementEditValues(tempRecord, 'LVLO\Reference'), ' ', true), GetElementNativeValues(tempRecord, 'LVLO\Level'));
end;
{ Debug } if debugMsg then
msgList('[ReplaceInLeveledListByList] slTemp := ', slTemp, ' );');
for x := 0 to bList.Count - 1 do
begin
if slContains(slTemp, bList[x]) then
begin
tempRecord := ObjectToElement(bList.Objects[x]);
if not slContains(slTemp, EditorID(tempRecord)) then
begin
// Detect Pre-Existing List or Create Override
if not(LoadOrder = GetLoadOrder(GetFile(LLrecord))) then
LLcopy := wbCopyElementToFile(LLrecord, aPlugin, false, true)
else
LLcopy := LLrecord;
// Replace
LLreplace(LLcopy, ObjectToElement(aList.Objects[x]), tempRecord);
end;
end;
end;
slTemp.clear;
end;
// Finalize
if ProcessTime then
begin
stopTime := Time;
addProcessTime('ReplaceInLeveledListByList', TimeBtwn(startTime, stopTime));
end;
slTemp.Free;
slLL.Free;
end;
// Find where the selected record is referenced in leveled lists and make a 'Copy as Override' into a specified file. Then replace all instances of templateRecord with inputRecord in the override
function AddToLeveledListAuto(templateRecord: IInterface; inputRecord: IInterface; aPlugin: IInterface): string;
var
LLrecord, LLcopy, masterRecord, inputEntry, tempRecord, tempelement: IInterface;
debugMsg, tempBoolean, AddToEnchanted, patchBool : boolean;
slRecords : TStringList;
i, x, y, tempInteger : integer;
patchFileName : string;
begin
// Begin debugMsg Section
debugMsg := true;
// Initialize
slRecords := TStringList.Create;
{ Debug } if debugMsg then
addMessage('[AddToLeveledListAuto] AddToLeveledListAuto(' + EditorID(templateRecord) + ', ' + EditorID(inputRecord) + ', ' + GetFileName(aPlugin) + ' );');
// Pull patch info if present
patchBool := slContains(slGlobal, 'Patch');
if patchBool then
patchFileName := GetFileName(ObjectToElement(GetObject('Patch', slGlobal)));
masterRecord := WinningOverride(templateRecord); { Debug }
if debugMsg then
addMessage('[AddToLeveledListAuto] masterRecord := ' + GetElementEditValues(masterRecord));
// This pulls the item out of chanceLeveledList in order to keep the addMessage statements consistent
{ Debug } if debugMsg then
addMessage('[AddToLeveledListAuto] if ' + Signature(inputRecord) + ' = ''LVLI'' then begin');
if (Signature(inputRecord) = 'LVLI') then
begin { Debug }
if debugMsg then
addMessage('[AddToLeveledListAuto] Pred(LLec(inputRecord)) := ' + IntToStr(Pred(LLec(inputRecord))));
for i := 0 to Pred(LLec(inputRecord)) do
begin { Debug }
if debugMsg then
addMessage('[AddToLeveledListAuto] inputEntry := ' + GetElementEditValues(LLelementbyindex(inputRecord, i)));
inputEntry := LLelementbyindex(inputRecord, i); { Debug }
if debugMsg then
addMessage('[AddToLeveledListAuto] if not (Signature(inputEntry) := ' + Signature(inputEntry) + ' = ''LVLI'') then Break; ');
if not(Signature(inputEntry) = 'LVLI') then
break;
end;
end else begin
inputEntry := templateRecord;
{ Debug } if debugMsg then
addMessage('[AddToLeveledListAuto] GetElementEditValues(inputEntry) := ' + GetElementEditValues(inputEntry) + ' EditorID(inputEntry := ' + EditorID(inputEntry));
end;
// addMessage('['+GetElementEditValues(inputEntry)+'] Processing '+IntToStr(ReferencedByCount(masterRecord))+' '+EditorID(inputEntry)+' References (This May Take A While)');
{ Debug } if debugMsg then
addMessage('[AddToLeveledListAuto] Pred(ReferencedByCount(masterRecord)) := ' + IntToStr(Pred(ReferencedByCount(masterRecord))));
// Begins analyzing records that reference masterRecord
for i := 0 to Pred(ReferencedByCount(masterRecord)) do
begin
LLrecord := ReferencedByIndex(masterRecord, i);
// Filter Invalid Entries
if patchBool then
if (GetFileName(GetFile(LLrecord)) <> patchFileName) then
Continue;
if ContainsText(EditorID(LLrecord), '++') or not(Length(EditorID(LLrecord)) > 0) or not IsHighestOverride(LLrecord, GetLoadOrder(aPlugin)) or not(Signature(LLrecord) = 'LVLI') or FlagCheck(LLrecord, 'Use All') or FlagCheck(LLrecord, 'Special Loot') then
Continue;
if slContains(slGlobal, EditorID(LLrecord)) then
if (EditorID(inputRecord) = EditorID(ObjectToElement(slGlobal.Objects[slGlobal.IndexOf(EditorID(LLrecord))]))) then
Continue;
slRecords.addObject(EditorID(LLrecord), LLrecord);
end;
// Add Masters
for i := 0 to slRecords.Count - 1 do
begin
LLrecord := ObjectToElement(slRecords.Objects[i]);
// Detect Pre-Existing List
{ Debug } if debugMsg then
addMessage('[AddToLeveledListAuto] LLcopy := MainRecordByEditorID(GroupBySignature(aPlugin, ''LVLI''), ' + EditorID(LLrecord) + ' );');
LLcopy := MainRecordByEditorID(GroupBySignature(aPlugin, 'LVLI'), EditorID(LLrecord));
// Create override if not already present
if not Assigned(LLcopy) then
LLcopy := wbCopyElementToFile(LLrecord, aPlugin, false, true);
RemoveInvalidEntries(LLcopy);
{ Debug } if debugMsg then
addMessage('[AddToLeveledListAuto] LLrecord := ' + EditorID(ReferencedByIndex(masterRecord, i)));
if not LLcontains(LLrecord, inputRecord) then
begin
tempelement := ElementByName(LLrecord, 'Leveled List Entries');
for x := 0 to Pred(LLec(LLrecord)) do
begin { Debug }
if debugMsg then
addMessage('[AddToLeveledListAuto] LLelementbyindex(LLrecord, x) := ' + EditorID(LLelementbyindex(LLrecord, x)));
{ Debug } if debugMsg then
addMessage('[AddToLeveledListAuto] if (GetLoadOrderFormID(masterRecord) := ' + IntToStr(GetLoadOrderFormID(masterRecord)) + ') = (GetLoadOrderFormID(LLelementbyindex(LLrecord, x)) := ' + IntToStr(GetLoadOrderFormID(LLelementbyindex(LLrecord, x))) + ') then begin');
tempRecord := elementbyindex(tempelement, x);
if GetElementEditValues(tempRecord, 'LVLO\Reference') = name(masterRecord) then
begin
tempInteger := 0;
tempInteger := GetElementNativeValues(tempRecord, 'LVLO\Level');
if not(tempInteger > 0) then
begin
addToLeveledList(LLcopy, inputRecord, 1);
end
else
addToLeveledList(LLcopy, inputRecord, tempInteger);
addMessage(EditorID(inputRecord) + ' added to ' + EditorID(LLrecord));
break;
end;
end;
end;
end;
debugMsg := false;
// End debugMsg section
end;
// Find where the selected record is referenced in leveled lists and make a 'Copy as Override' into a specified file. Then replace all instances of templateRecord with inputRecord in the override
procedure AddToLeveledListByList(aList: TStringList; aPlugin: IInterface);
var
LLrecord, LLcopy, masterRecord, tempRecord, tempelement: IInterface;
startTime, stopTime, tempStart, tempStop : TDateTime;
i, x, y, tempInteger, LoadOrder : integer;
debugMsg, tempBoolean, Patch : boolean;
slLL, slTemp, slTempList : TStringList;
tempString : string;
begin
// Initialize
debugMsg := true;
startTime := Time;
slTempList := TStringList.Create;
slTemp := TStringList.Create;
slTemp.Sorted := true;
slTemp.Duplicates := dupIgnore;
slLL := TStringList.Create;
{ Debug } if debugMsg then
begin
addMessage('[AddToLeveledListByList] AddToLeveledListByList(aList, ' + GetFileName(aPlugin) + ' );');
addMessage(' ');
msgList('[AddToLeveledListByList] slGlobal := ', slGlobal, '');
addMessage(' ');
msgList('[AddToLeveledListByList] aList := ', aList, '');
addMessage(' ');
for i := 0 to slGlobal.Count - 1 do
if ContainsText(slGlobal[i], '-//-') then
addMessage('[AddToLeveledListByList] ' + slGlobal[i] + ' := ' + EditorID(ObjectToElement(slGlobal.Objects[i])));
for i := 0 to slGlobal.Count - 1 do
if ContainsText(slGlobal[i], '-/Level/-') then
addMessage('[AddToLeveledListByList] ' + slGlobal[i] + ' := ' + IntToStr(integer(slGlobal.Objects[i])));
end;
Patch := slContains(slGlobal, 'Patch');
LoadOrder := GetLoadOrder(aPlugin);
// Add Masters
{ Debug } if debugMsg then
addMessage('[AddToLeveledListByList] Adding Masters');
// Collect leveled lists
addMessage('Beginning Leveled List Collection');
// Custom Leveled List Input
for i := 0 to slGlobal.Count - 1 do
if ContainsText(slGlobal[i], '-/LeveledList/-') then
slLL.addObject(StrPosCopy(slGlobal[i], '-/LeveledList/-', true), slGlobal.Objects[i]);
// Leveled list from template
for i := 0 to aList.Count - 1 do
begin
masterRecord := ObjectToElement(aList.Objects[i]);
tempString := EditorID(masterRecord);
// If two records have the same template this prevents it from getting processed twice
{ Debug } if debugMsg then
addMessage('[AddToLeveledListByList] If two records have the same template this prevents it from getting processed twice');
if slContains(slTemp, tempString) then
Continue
else
slTemp.Add(tempString);
{ Debug } if debugMsg then
msgList('[AddToLeveledListByList] ', slTemp, '');
addMessage('[' + IntToStr(i + 1) + '/' + IntToStr(aList.Count) + '] Collecting ' + tempString + ' Leveled Lists');
{ Debug } if debugMsg then
addMessage('[AddToLeveledListByList] for x := 0 to ' + IntToStr(Pred(ReferencedByCount(masterRecord))) + ' do begin');
for x := 0 to Pred(ReferencedByCount(masterRecord)) do
begin
LLrecord := ReferencedByIndex(masterRecord, x);
tempString := EditorID(LLrecord);
{ Debug } if debugMsg then
addMessage('[AddToLeveledListByList] EditorID(LLrecord) := ' + tempString);
// Filter Invalid Entries
{ Debug } if debugMsg then
addMessage('[AddToLeveledListByList] Filter Invalid Entries');
if slContains(slLL, tempString) then
Continue;
if ContainsText(tempString, '++') or (Length(tempString) <= 0) or not IsHighestOverride(LLrecord, LoadOrder) or not(Signature(LLrecord) = 'LVLI') or FlagCheck(LLrecord, 'Use All') or FlagCheck(LLrecord, 'Special Loot') then
Continue;
if not(LoadOrder >= GetLoadOrder(GetFile(LLrecord))) then
begin
if PreviousOverrideExists(LLrecord, LoadOrder) then
begin
LLrecord := GetPreviousOverride(LLrecord, LoadOrder);
end
else
Continue;
end
else
if debugMsg then
addMessage('[AddToLeveledListByList] ' + EditorID(LLrecord) + ' := ' + IntToStr(LoadOrder) + ' >= ' + IntToStr(GetLoadOrder(GetFile(LLrecord))));
// Restricts the valid leveled lists to a single file (for 'Patch' function)
{ Debug } if debugMsg then
addMessage('[AddToLeveledListByList] Restricts the valid leveled lists to a single file (for Patch function)');
if Patch then
begin
tempString := GetFileName(ObjectToElement(GetObject('Patch', slGlobal)));
tempBoolean := false;
// {Debug} if debugMsg then addMessage('[AddToLeveledListByList] for x := 0 to '+IntToStr(Pred(OverrideCount(LLrecord)))+' do begin');
if (OverrideCount(LLrecord) > 0) then
begin
for y := 0 to Pred(OverrideCount(LLrecord)) do
begin
{ Debug } if debugMsg then
addMessage('[AddToLeveledListByList] if (GetFileName(GetFile(OverrideByIndex(' + EditorID(LLrecord) + ', ' + IntToStr(x) + '))) = ' + tempString + ') then begin');
if (GetFileName(GetFile(OverrideByIndex(LLrecord, y))) = tempString) then
begin
tempBoolean := true;
break;
end;
end;
end
else
if (GetFileName(GetFile(LLrecord)) = tempString) then
tempBoolean := true;
if not tempBoolean then
Continue;
end;
// Add Copy to List
slLL.addObject(EditorID(LLrecord), LLrecord);
end;
end;
{ Debug } if debugMsg then
msgList('[AddToLeveledListByList] slLL := ', slLL, ' );');
// Add Masters
tempStart := Time;
tempStop := Time;
// addProcessTime('Add Masters', TimeBtwn(tempStart, tempStop));
// Process Leveled Lists
addMessage('Processing Leveled Lists');
for i := 0 to slLL.Count - 1 do
begin
slTempList.clear;
slTemp.clear;
LLrecord := ObjectToElement(slLL.Objects[i]);
{ Debug } if debugMsg then
addMessage('[AddToLeveledListByList] LLrecord := ' + EditorID(LLrecord));
if (Length(EditorID(LLrecord)) <= 0) then
Continue;
tempelement := ElementByName(LLrecord, 'Leveled List Entries');
for x := 0 to Pred(LLec(LLrecord)) do
begin
tempRecord := elementbyindex(tempelement, x);
slTemp.addObject(StrPosCopy(GetElementEditValues(tempRecord, 'LVLO\Reference'), ' ', true), StrToInt(GetElementEditValues(tempRecord, 'LVLO\Level'))); { Debug }
if debugMsg then
addMessage('[AddToLeveledListByList] slTemp.AddObject(' + StrPosCopy(GetElementEditValues(tempRecord, 'LVLO\Reference'), ' ', true) + ', ' + IntToStr(StrToInt(GetElementEditValues(tempRecord, 'LVLO\Level'))) + ' )');
end; { Debug }
if debugMsg then
msgList('[AddToLeveledListByList] slTemp := ', slTemp, '');
for x := 0 to aList.Count - 1 do
begin
tempRecord := ObjectToElement(GetObject(aList[x], slGlobal));
{ Debug } if debugMsg then
addMessage('[AddToLeveledListByList] tempRecord := ' + EditorID(tempRecord));
tempInteger := -1;
// Custom input from 'Add To Leveled List' menu
tempString := EditorID(LLrecord) + '-/Level/-' + EditorID(tempRecord);
if slContains(slGlobal, tempString) then
begin
tempInteger := integer(GetObject(tempString, slGlobal)); { Debug }
if debugMsg then
addMessage('[AddToLeveledListByList] Custom Level for ' + EditorID(tempRecord) + ' in ' + EditorID(LLrecord) + ' := ' + IntToStr(tempInteger));
slGlobal.Delete(slGlobal.IndexOf(tempString));
slGlobal.Delete(slGlobal.IndexOf(EditorID(LLrecord) + '-/LeveledList/-' + EditorID(tempRecord)));
if (tempInteger <= 0) then
Continue;
end;
// Level from template
if (tempInteger = -1) then
begin
tempString := EditorID(ObjectToElement(aList.Objects[x]));
if slContains(slTemp, tempString) then
tempInteger := integer(GetObject(tempString, slTemp));
end;
{ Debug } if debugMsg then
addMessage('[AddToLeveledListByList] Level from ' + EditorID(LLrecord) + ' := ' + IntToStr(tempInteger));
if (tempInteger = -1) then
Continue;
if (tempInteger = 0) then
tempInteger := 1;
// Detect Pre-Existing List or Create Override
case GetLoadOrder(GetFile(LLrecord)) of
LoadOrder:
LLcopy := LLrecord;
else
LLcopy := wbCopyElementToFile(LLrecord, aPlugin, false, true);
end;
{ Debug } if debugMsg then
addMessage('[AddToLeveledListByList] LLcopy := ' + EditorID(LLcopy));
if not slContains(slTemp, EditorID(tempRecord)) then
begin
addToLeveledList(LLcopy, tempRecord, tempInteger); { Debug }
if debugMsg then
addMessage('[AddToLeveledListByList] addToLeveledList(' + EditorID(LLcopy) + ', ' + EditorID(tempRecord) + ', ' + IntToStr(tempInteger) + ' )');
slTempList.Add(EditorID(tempRecord));
end;
end;
if (slTempList.Count > 0) then
msgList('[' + IntToStr(i + 1) + '/' + IntToStr(slLL.Count) + '] ' + EditorID(LLrecord) + ' added: ', slTempList, '');
end;
// Finalize
stopTime := Time;
if ProcessTime then
addProcessTime('AddToLeveledListByList', TimeBtwn(startTime, stopTime));
slTempList.Free;
slTemp.Free;
slLL.Free;
end;
// Find where the selected record is referenced in leveled lists and make a 'Copy as Override' into a specified file. Then replace all instances of templateRecord with inputRecord in the override
procedure AddOutfitByList(aList: TStringList; aPlugin: IInterface);
var
LLrecord, LLcopy, masterRecord, tempRecord, tempelement, currentElement, primarySlotItem: IInterface;
startTime, stopTime, tempStart, tempStop : TDateTime;
i, x, y, tempInteger, LoadOrder, tempCount, currentCount : integer;
debugMsg, tempBoolean, Patch : boolean;
slLL, slTemp, slTempList, slItem, slNames, slOutfits : TStringList;
tempString, commonString, Slot : string;
begin
// Initialize
debugMsg := false;
startTime := Time;
slTempList := TStringList.Create;
slTemp := TStringList.Create;
slTemp.Sorted := true;
slTemp.Duplicates := dupIgnore;
slOutfits := TStringList.Create;
slNames := TStringList.Create;
slItem := TStringList.Create;
slLL := TStringList.Create;
{ Debug } if debugMsg then
begin // Seperates the debug messages so they're a little easier to read
addMessage('[AddOutfitByList] AddOutfitByList(aList, ' + GetFileName(aPlugin) + ' );');
addMessage(' ');
msgList('[AddOutfitByList] slGlobal := ', slGlobal, '');
addMessage(' ');
msgList('[AddOutfitByList] aList := ', aList, '');
addMessage(' ');
for i := 0 to slGlobal.Count - 1 do
if ContainsText(slGlobal[i], '-//-') then
addMessage('[AddOutfitByList] ' + slGlobal[i] + ' := ' + EditorID(ObjectToElement(slGlobal.Objects[i])));
for i := 0 to slGlobal.Count - 1 do
if ContainsText(slGlobal[i], '-/Level/-') then
addMessage('[AddOutfitByList] ' + slGlobal[i] + ' := ' + IntToStr(integer(slGlobal.Objects[i])));
end;
Patch := slContains(slGlobal, 'Patch'); // Whether or not we're using the 'Patch' QOL function
LoadOrder := GetLoadOrder(aPlugin);
// Add Masters
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] Adding Masters');
// Collect Outfits
for i := 0 to aList.Count - 1 do
begin // Collect names
if not(Signature(ObjectToElement(aList.Objects[i])) = 'ARMO') then
Continue;
tempRecord := ObjectToElement(GetObject(aList[i], slGlobal));
slNames.addObject(Full(tempRecord), tempRecord);
end;
slTemp.CommaText := 'Bracers, Gloves, Glove, Cloak, Underwear, Panties, Lingerie, Skirt, Armlets, Armlet, Gauntlets, Helmet, Crown, Helm, Hood, Mask, Circlet, Headdress, Shield, Buckler, Boots, Shoes, Cuirass, Armor, Top, Pants, Robes, Scarf, Clothes, Cape, Hooded';
for i := 0 to slTemp.Count - 1 do // Remove junk words
RemoveSubStr(slNames, slTemp[i]);
{ Debug } if debugMsg then
msgList('[AddOutfitByList] slNames := ', slNames, '');
tempInteger := 0; // Keeps track of where we are in the list
while (slNames.Count > tempInteger) do
begin // while tier 3
tempBoolean := false; // Keeps track of whether or not the current entry is deleted
if not(GetPrimarySlot(ObjectToElement(slNames.Objects[tempInteger])) = '00') then
begin // Skips primary slot items
Inc(tempInteger);
Continue;
end;
commonString := Trim(slNames[tempInteger]); // String we're searching for
while (Length(commonString) > 0) do
begin // While tier 2
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] commonString := ' + commonString);
slTemp.clear;
for i := 0 to slNames.Count - 1 do
begin
if ContainsText(slNames[i], commonString) then
begin // if there's another item with the same prefix add it to slTemp
tempelement := ObjectToElement(slNames.Objects[i]);
slTemp.addObject(EditorID(tempelement), tempelement);
end;
end;
if (slTemp.Count > 1) then
begin // If there's more than one item with the same name assemble an outfit
{ Debug } if debugMsg then
msgList('[AddOutfitByList] slTemp := ', slTemp, '');
tempCount := 0; // Using the same trick again to keep track of where we are in the list
while (slTemp.Count > tempCount) do
begin // while tier 3
slItem.clear;
tempRecord := ObjectToElement(slTemp.Objects[tempCount]);
Slot := GetPrimarySlot(tempRecord);
if (Slot <> '00') then
begin // Skips primary slot items
Inc(tempCount);
Continue;
end;
slGetFlagValues(tempRecord, slItem, false); // Get the BOD2 for this non-primary slot item
AddPrimarySlots(slItem); // Associate with primary slot
primarySlotItem := nil;
for i := 0 to slTemp.Count - 1 do
begin // Associate the non-primary slot item with a primary-slot one of the same type
if (i = tempCount) then
Continue;
tempelement := ObjectToElement(slTemp.Objects[i]);
tempString := GetPrimarySlot(tempelement);
if slContains(slItem, tempString) then
begin // if the outfit contains a primary slot item equal to the primary slot associated with this item then begin
primarySlotItem := tempelement;
Slot := tempString;
break;
end;
end;
if Assigned(primarySlotItem) then
begin
LLrecord := MainRecordByEditorID(GroupBySignature(aPlugin, 'LVLI'), EditorID(primarySlotItem) + 'SubList');
if not Assigned(LLrecord) then
LLrecord := createLeveledList(aPlugin, EditorID(primarySlotItem) + 'SubList', slTempList, 0); // Create a 'Use All' leveled list to contain all the non-primary slot items associated with this primary slot
end else begin // if there isn't a same-type primary slot use any primary-slot item
for i := 0 to slTemp.Count - 1 do
begin // Associate the non-primary slot item with a primary-slot one of the same type
if (i = tempCount) then
Continue;
tempelement := ObjectToElement(slTemp.Objects[i]);
tempString := GetPrimarySlot(tempelement);
if (GetPrimarySlot(tempelement) <> '00') then
begin // if the outfit contains a primary slot item equal to the primary slot associated with this item then begin
primarySlotItem := tempelement;
Slot := tempString;
break;
end;
end;
if Assigned(primarySlotItem) then
begin // This is a hard-coded addition since this item won't be associated with the primary slot item in the main addition section
LLrecord := MainRecordByEditorID(GroupBySignature(aPlugin, 'LVLI'), EditorID(primarySlotItem) + 'SubList');
if not Assigned(LLrecord) then
LLrecord := createLeveledList(aPlugin, EditorID(primarySlotItem) + 'SubList', slTempList, 0); // Create a 'Use All' leveled list to contain all the non-primary slot items associated with this primary slot
if not LLcontains(LLrecord, tempRecord) then
begin
addToLeveledList(LLrecord, tempRecord, 1);
y := IndexOfObjectEDID(EditorID(tempRecord), slNames);
if (y <> -1) then
begin
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] slNames.Delete (' + EditorID(ObjectToElement(slNames.Objects[y])) + ');');
slNames.Delete(y); // Remove from name list
end;
slTemp.Delete(tempCount); // Remove from outfit list
if slContains(aList, EditorID(tempRecord) + 'Original') then
begin
{ Debug } if debugMsg then
addMessage('slContains(aList, ' + EditorID(tempRecord) + ') then begin');
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] aList.Delete (' + aList[aList.IndexOf(EditorID(tempRecord) + 'Original')] + ');');
aList.Delete(aList.IndexOf(EditorID(tempRecord) + 'Original')); // Remove from leveled list addition
end;
end;
end;
end;
if not Assigned(primarySlotItem) then
break; // if there aren't any primary slot items in this outfit skip it entirely
// Leveled List Addition
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] primarySlotItem := ' + EditorID(primarySlotItem));
// Create Leveled List
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] Begin Outfit Creation');
slTempList.CommaText := '"Use All"';
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] addToLeveledList(' + EditorID(LLrecord) + ', ' + EditorID(primarySlotItem) + '), 1);');
if not LLcontains(LLrecord, primarySlotItem) then
addToLeveledList(LLrecord, primarySlotItem, 1);
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] LLrecord := ' + EditorID(LLrecord));
currentCount := 0; // Last 'while' loop, I promise
for currentCount := pred(slTemp.count) downto 0 do
begin// Get all outfit items that are associated with this slot
currentElement := ObjectToElement(slTemp.Objects[currentCount]);
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] currentElement := ' + EditorID(currentElement));
if not(GetPrimarySlot(currentElement) = '00') then
begin // Skips primary slot items
Continue;
end;
slItem.clear;
slGetFlagValues(currentElement, slItem, false); // Get BOD2 slots
AddPrimarySlots(slItem); // Associate BOD2 with a primary slot
{ Debug } if debugMsg then
msgList('[AddOutfitByList] ' + EditorID(currentElement) + ' Element BOD2 := ', slItem, '');
{ Debug } if debugMsg then
msgList('[AddOutfitByList] if slContains (', slItem, '), ' + Slot);
if slContains(slItem, Slot) then
begin // if its associated with the current slot add it to the leveled list
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] addToLeveledList(' + EditorID(LLrecord) + ', ' + EditorID(currentElement) + '), 1);');
if not LLcontains(LLrecord, currentElement) then
addToLeveledList(LLrecord, currentElement, 1);
y := IndexOfObjectEDID(EditorID(currentElement), slNames);
if (y <> -1) then
begin
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] slNames.Delete (' + EditorID(ObjectToElement(slNames.Objects[y])) + ');');
slNames.Delete(y); // Remove from name list
end;
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] slTemp.Delete (' + slTemp[currentCount] + ');');
slTemp.Delete(currentCount); // Remove from outfit list
if slContains(aList, EditorID(currentElement) + 'Original') then
begin
{ Debug } if debugMsg then
addMessage('slContains(aList, ' + EditorID(currentElement) + ') then begin');
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] aList.Delete (' + aList[aList.IndexOf(EditorID(currentElement) + 'Original')] + ');');
aList.Delete(aList.IndexOf(EditorID(currentElement) + 'Original')); // Remove from leveled list addition
end;
if (currentCount = 0) then
tempBoolean := true; // Only need to delete the current element in the master 'while' loop once
end;
end;
if (LLec(LLrecord) > 1) then
begin
if not slContains(slOutfits, EditorID(LLrecord)) then
slOutfits.addObject(EditorID(LLrecord), LLrecord);
end
else
Remove(LLrecord);
end; // while tier 3 end
break; // if an outfit was assembled from this string exit the while loop
end;
if ContainsText(commonString, ' ') then
begin // If an outfit is not found, shorten the number of words by 1 and check again
commonString := Trim(StrPosCopy(commonString, ' ', true));
end
else
break;
end; // while tier 2 end
if not tempBoolean then // if not already deleted
slNames.Delete(tempInteger); // Remove the name we just checked for
end; // while tier 1 end
{ Debug } if debugMsg then
msgList('[AddOutfitByList] slOutfits := ', slOutfits, '');
{ Debug } if debugMsg then
msgList('[AddOutfitByList] aList := ', aList, '');
// Collect leveled lists
addMessage('Beginning Leveled List Collection');
// Custom Leveled List Input
for i := 0 to slGlobal.Count - 1 do
if ContainsText(slGlobal[i], '-/LeveledList/-') then
slLL.addObject(StrPosCopy(slGlobal, '-/LeveledList/-', true), slGlobal.Objects[i]);
// Leveled list from template
for i := 0 to aList.Count - 1 do
begin
masterRecord := ObjectToElement(aList.Objects[i]);
tempString := EditorID(masterRecord);
// If two records have the same template this prevents it from getting processed twice
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] If two records have the same template this prevents it from getting processed twice');
if slContains(slTemp, tempString) then
Continue
else
slTemp.Add(tempString);
{ Debug } if debugMsg then
msgList('[AddOutfitByList] ', slTemp, '');
addMessage('[' + IntToStr(i + 1) + '/' + IntToStr(aList.Count) + '] Collecting ' + tempString + ' Leveled Lists');
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] for x := 0 to ' + IntToStr(Pred(ReferencedByCount(masterRecord))) + ' do begin');
for x := 0 to Pred(ReferencedByCount(masterRecord)) do
begin
LLrecord := ReferencedByIndex(masterRecord, x);
tempString := EditorID(LLrecord);
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] EditorID(LLrecord) := ' + tempString);
// Filter Invalid Entries
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] Filter Invalid Entries');
if slContains(slLL, tempString) then
Continue;
if ContainsText(tempString, '++') or (Length(tempString) <= 0) or not IsHighestOverride(LLrecord, LoadOrder) or not(Signature(LLrecord) = 'LVLI') or FlagCheck(LLrecord, 'Use All') or FlagCheck(LLrecord, 'Special Loot') then
Continue;
if not(LoadOrder >= GetLoadOrder(GetFile(LLrecord))) then
begin
if PreviousOverrideExists(LLrecord, LoadOrder) then
begin
LLrecord := GetPreviousOverride(LLrecord, LoadOrder);
end
else
Continue;
end
else
if debugMsg then
addMessage('[AddOutfitByList] ' + EditorID(LLrecord) + ' := ' + IntToStr(LoadOrder) + ' >= ' + IntToStr(GetLoadOrder(GetFile(LLrecord))));
// Restricts the valid leveled lists to a single file (for 'Patch' function)
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] Restricts the valid leveled lists to a single file (for Patch function)');
if Patch then
begin
tempString := GetFileName(ObjectToElement(GetObject('Patch', slGlobal)));
tempBoolean := false;
// {Debug} if debugMsg then addMessage('[AddOutfitByList] for x := 0 to '+IntToStr(Pred(OverrideCount(LLrecord)))+' do begin');
if (OverrideCount(LLrecord) > 0) then
begin
for y := 0 to Pred(OverrideCount(LLrecord)) do
begin
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] if (GetFileName(GetFile(OverrideByIndex(' + EditorID(LLrecord) + ', ' + IntToStr(x) + '))) = ' + tempString + ') then begin');
if (GetFileName(GetFile(OverrideByIndex(LLrecord, y))) = tempString) then
begin
tempBoolean := true;
break;
end;
end;
end
else
if (GetFileName(GetFile(LLrecord)) = tempString) then
tempBoolean := true;
if not tempBoolean then
Continue;
end;
// Add Copy to List
slLL.addObject(EditorID(LLrecord), LLrecord);
end;
end;
{ Debug } if debugMsg then
msgList('[AddOutfitByList] slLL := ', slLL, ' );');
// Add Masters
tempStart := Time;
tempStop := Time;
// addProcessTime('Add Masters', TimeBtwn(tempStart, tempStop));
// Process Leveled Lists
addMessage('Processing Leveled Lists');
for i := 0 to slLL.Count - 1 do
begin
slTempList.clear;
slTemp.clear;
LLrecord := ObjectToElement(slLL.Objects[i]);
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] LLrecord := ' + EditorID(LLrecord));
if (Length(EditorID(LLrecord)) <= 0) then
Continue tempelement := ElementByName(LLrecord, 'Leveled List Entries');
for x := 0 to Pred(LLec(LLrecord)) do
begin
tempRecord := elementbyindex(tempelement, x);
slTemp.addObject(StrPosCopy(GetElementEditValues(tempRecord, 'LVLO\Reference'), ' ', true), StrToInt(GetElementEditValues(tempRecord, 'LVLO\Level'))); { Debug }
if debugMsg then
addMessage('[AddOutfitByList] slTemp.AddObject(' + StrPosCopy(GetElementEditValues(tempRecord, 'LVLO\Reference'), ' ', true) + ', ' + IntToStr(StrToInt(GetElementEditValues(tempRecord, 'LVLO\Level'))) + ' )');
end; { Debug }
if debugMsg then
msgList('[AddOutfitByList] slTemp := ', slTemp, '');
for x := 0 to aList.Count - 1 do
begin
tempRecord := ObjectToElement(GetObject(aList[x], slGlobal));
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] tempRecord := ' + EditorID(tempRecord));
tempInteger := -1;
// Custom input from 'Add To Leveled List' menu
tempString := EditorID(LLrecord) + '-/Level/-' + EditorID(tempRecord);
if slContains(slGlobal, tempString) then
begin
tempInteger := integer(GetObject(tempString, slGlobal)); { Debug }
if debugMsg then
addMessage('[AddOutfitByList] Custom Level for ' + EditorID(tempRecord) + ' in ' + EditorID(LLrecord) + ' := ' + IntToStr(tempInteger));
slGlobal.Delete(slGlobal.IndexOf(tempString));
slGlobal.Delete(slGlobal.IndexOf(EditorID(LLrecord) + '-/LeveledList/-' + EditorID(tempRecord)));
if (tempInteger <= 0) then
Continue;
end;
// Level from template
if (tempInteger = -1) then
begin
tempString := EditorID(ObjectToElement(aList.Objects[x]));
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] Find Template := ' + tempString);
if slContains(slTemp, tempString) then
tempInteger := slTemp.Objects[slTemp.IndexOf(tempString)];
end;
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] Level from ' + EditorID(LLrecord) + ' := ' + IntToStr(tempInteger));
if (tempInteger = -1) then
Continue;
if (tempInteger = 0) then
tempInteger := 1;
// Detect Pre-Existing List or Create Override
case GetLoadOrder(GetFile(LLrecord)) of
LoadOrder:
LLcopy := LLrecord;
else
LLcopy := wbCopyElementToFile(LLrecord, aPlugin, false, true);
end;
{ Debug } if debugMsg then
addMessage('[AddOutfitByList] LLcopy := ' + EditorID(LLcopy));
if not slContains(slTemp, EditorID(tempRecord)) then
begin
// {Debug} if debugMsg then msgList('[AddOutfitByList] if slContains(', slOutfits, '), '''+EditorID(tempRecord)+'SubList then');
if slContains(slOutfits, EditorID(tempRecord) + 'SubList') then // if non-primary slots have been associated with this item add it instead
tempRecord := ObjectToElement(slOutfits.Objects[slOutfits.IndexOf(EditorID(tempRecord) + 'SubList')]);
addToLeveledList(LLcopy, tempRecord, tempInteger); { Debug }
if debugMsg then
addMessage('[AddOutfitByList] addToLeveledList(' + EditorID(LLcopy) + ', ' + EditorID(tempRecord) + ', ' + IntToStr(tempInteger) + ' )');
slTempList.Add(EditorID(tempRecord));
end;
end;
if (slTempList.Count > 0) then
msgList('[' + IntToStr(i + 1) + '/' + IntToStr(slLL.Count) + '] ' + EditorID(LLrecord) + ' added: ', slTempList, '');
end;
// Finalize
stopTime := Time;
if ProcessTime then
addProcessTime('AddOutfitByList', TimeBtwn(startTime, stopTime));
slOutfits.Free;
slNames.Free;
slTempList.Free;
slTemp.Free;
slItem.Free;
slLL.Free;
end;
// Reassembles and then adds to all outfits containing inputRecord
function AddToOutfitAuto(templateRecord: IInterface; inputRecord: IInterface; aPlugin: IInterface): string;
var
tempLevelList, tempRecord, tempelement, masterLevelList, baseLevelList, subLevelList, vanillaLevelList, masterRecord, LVLIrecord, OTFTrecord, OTFTitems, OTFTitem, OTFTcopy, LLentry, Record_edid: IInterface;
debugMsg, tempBoolean, LightArmorBoolean, HeavyArmorBoolean : boolean;
tempInteger, i, x, y, z, a, b : integer;
slTemp, slTempObject, slOutfit, slpair, slItem, slEnchantedList, slLevelList, slBlackList, slStringList, sl1, sl2 : TStringList;
tempString, String1, commonString, OTFTrecord_edid : string;
begin
// If the OTFT draws from a series of level lists assemble complete outfits from the items in those lists.
// In most cases OTFT records draw from a level list for each piece of the outfit (e.g. boots level list, helmet level list, etc.)
// Identifies and assembles based on BOD2 slots
// This assembles a level list of the entire 'Steel Plate' outfit so that npcs will USUALLY spawn with a complete outfit instead of a hodge-podge drawn from various level lists
// This does not edit or remove the original list. The original entries remain intact as a single outfit within the complete list of outfits in masterLevelList.
// This means that, if there is 1 level list of the original outfit, 9 outfits are detected and assembled, and the script is adding 1 outfit, then you will StrToIntll have a 1/11 chance for a hodge-podge outfit <-- (1+9+1)
// This is intended. The goal is to improve the outfits, NEVER to remove existing entries or functionality (even if there is a lower chance to find those items).
// The output should be A) A LL of selected Records B) LLs of outfit's original records C) A LL consiStrToIntng of the leftovers
// Begin debugMsg Section
debugMsg := false;
// Initialize
if not Assigned(slEnchantedList) then
slEnchantedList := TStringList.Create
else
slEnchantedList.clear;
if not Assigned(slStringList) then
slStringList := TStringList.Create
else
slStringList.clear;
if not Assigned(slTempObject) then
slTempObject := TStringList.Create
else
slTempObject.clear;
if not Assigned(slBlackList) then
slBlackList := TStringList.Create
else
slBlackList.clear;
if not Assigned(slLevelList) then
slLevelList := TStringList.Create
else
slLevelList.clear;
if not Assigned(slOutfit) then
slOutfit := TStringList.Create
else
slOutfit.clear;
if not Assigned(slItem) then
slItem := TStringList.Create
else
slItem.clear;
if not Assigned(slTemp) then
slTemp := TStringList.Create
else
slTemp.clear;
if not Assigned(slpair) then
slpair := TStringList.Create
else
slpair.clear;
if not Assigned(sl1) then
sl1 := TStringList.Create
else
sl1.clear;
if not Assigned(sl2) then
sl2 := TStringList.Create
else
sl2.clear;
// Common Function Output
masterRecord := MasterOrSelf(templateRecord);
/// /////////////////////////////////////////////////////////////////// OTFT RECORD DETECTION ///////////////////////////////////////////////////////////////////////////////////////
// Find valid OTFT records
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] Begin OTFT Record Detection');
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] for i := 0 to Pred(ReferencedByCount(masterRecord)) :=' + IntToStr(Pred(ReferencedByCount(masterRecord))) + ' do begin');
for i := 0 to Pred(ReferencedByCount(masterRecord)) do
begin { Debug }
if debugMsg then
addMessage('[AddToOutfitAuto] LVLIrecord := ' + EditorID(ReferencedByIndex(masterRecord, i)));
slTempObject.clear;
LVLIrecord := ReferencedByIndex(masterRecord, i); { Debug }
if debugMsg then
addMessage('[AddToOutfitAuto] if (Signature(LVLIrecord) := ' + Signature(LVLIrecord) + '= ''LVLI'') then begin');
if (Signature(LVLIrecord) = 'LVLI') then
begin
// Check for outfits that reference a list of items of a specific type (e.g. Boots, Gauntlets)
while (Signature(LVLIrecord) = 'LVLI') do
begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] for x := 0 to Pred(ReferencedByCount(LVLIrecord)) := ' + IntToStr(Pred(ReferencedByCount(LVLIrecord))) + ' do begin');
for x := 0 to Pred(ReferencedByCount(LVLIrecord)) do
begin { Debug }
if debugMsg then
addMessage('[AddToOutfitAuto] OTFTrecord := ReferencedByIndex(LVLIrecord, x) := ' + EditorID(ReferencedByIndex(LVLIrecord, x)) + ';');
OTFTrecord := ReferencedByIndex(LVLIrecord, x); { Debug }
if debugMsg then
addMessage('[AddToOutfitAuto] if IsWinningOVerride(OTFTrecord) := ' + BoolToStr(IsWinningOVerride(OTFTrecord)) + ' and (Signature(OTFTrecord) := ' + Signature(OTFTrecord) + ' = ''OTFT'') and ContainsText(EditorID(OTFTrecord), ''Armor'') := ' + BoolToStr(ContainsText(EditorID(OTFTrecord), 'Armor')) + ' then begin');
if (Signature(OTFTrecord) = 'OTFT') then
begin
if not IsWinningOVerride(OTFTrecord) then
Continue;
// Check if OTFT references LVLI or is referenced more than once (to exclude outfits specifically for a single NPC)
tempBoolean := false;
if (ReferencedByCount(OTFTrecord) > 1) then
tempBoolean := true;
if not tempBoolean then
for y := 0 to Pred(ElementCount(ElementByPath(OTFTrecord, 'INAM'))) do
if (Signature(elementbyindex(ElementByPath(OTFTrecord, 'INAM'), y)) = 'LVLI') then
tempBoolean := true;
if tempBoolean and (Signature(OTFTrecord) = 'OTFT') then
if not slContains(slOutfit, EditorID(OTFTrecord)) then
slOutfit.addObject(EditorID(OTFTrecord), OTFTrecord);
end
else
if (Signature(LVLIrecord) = 'LVLI') then
begin
slTempObject.addObject(EditorID(OTFTrecord), OTFTrecord);
end;
end;
if (slTempObject.Count > 0) then
begin
LVLIrecord := ObjectToElement(slTempObject.Objects[0]);
slTempObject.Delete(0);
end else begin
break;
end;
end;
end else begin
OTFTrecord := ReferencedByIndex(masterRecord, i); { Debug }
if debugMsg then
addMessage('[AddToOutfitAuto] if (Signature(OTFTrecord) := ' + Signature(OTFTrecord) + '= ''LVLI'') then begin');
if IsWinningOVerride(OTFTrecord) and (Signature(OTFTrecord) = 'OTFT') then
if not slContains(slOutfit, EditorID(OTFTrecord)) then
slOutfit.addObject(EditorID(OTFTrecord), OTFTrecord);
end;
end;
/// /////////////////////////////////////////////////////////////////// RESTRUCTURE OTFT RECORDS ///////////////////////////////////////////////////////////////////////////////////
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] FormID Detection Complete; Restructuring OTFT records');
{ Debug } if debugMsg then
msgList('[AddToOutfitAuto] slOutfit := ', slOutfit, '');
if not(slOutfit.Count > 0) then
Continue;
for i := 0 to slOutfit.Count - 1 do
begin
OTFTcopy := nil;
OTFTrecord := WinningOverride(ObjectToElement(slOutfit.Objects[i])); { Debug }
if debugMsg then
addMessage('[AddToOutfitAuto] OTFTrecord := ' + EditorID(OTFTrecord));
OTFTrecord_edid := EditorID(OTFTrecord);
// Add Masters
OTFTitems := ElementByPath(OTFTrecord, 'INAM');
// Check for a previous script run
if (ElementCount(OTFTitems) = 1) and (Signature(LinksTo(elementbyindex(OTFTitems, 0))) = 'LVLI') then
begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] if tempInteger = 1 end else begin');
masterLevelList := MainRecordByEditorID(GroupBySignature(aPlugin, 'LVLI'), (OTFTrecord_edid + '_Master'));
// This is for outfits with a single level list that can be used in a new masterLevelList
if not Assigned(masterLevelList) then
begin
slTemp.CommaText := '"Use All"';
masterLevelList := createLeveledList(aPlugin, OTFTrecord_edid + '_Master', slTemp, 0);
vanillaLevelList := LinksTo(elementbyindex(OTFTitems, 0));
for y := 0 to 3 do
addToLeveledList(masterLevelList, vanillaLevelList, 1);
addToLeveledList(masterLevelList, inputRecord, 1);
end;
// This section restructures the outfit if this is the first time the script is editing this outfit
end else begin
// Preps the leveled lists
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] Creating a new vanillaLevelList and masterLevelList if not already present');
// Check if aPlugin already has a leveled list created for vanillaLevelList
vanillaLevelList := MainRecordByEditorID(GroupBySignature(aPlugin, 'LVLI'), (OTFTrecord_edid + '_Original'));
{ Debug } if debugMsg and Assigned(vanillaLevelList) then
addMessage('[AddToOutfitAuto] Pre-existing vanillaLevelList := ' + EditorID(vanillaLevelList))
{ Debug } else
if debugMsg and not Assigned(vanillaLevelList) then
addMessage('[AddToOutfitAuto] Pre-existing vanillaLevelList not detected');
if not Assigned(vanillaLevelList) then
begin
if (ElementCount(OTFTitems) > 1) then
begin
slTemp.CommaText := '"Use All"';
vanillaLevelList := createLeveledList(aPlugin, OTFTrecord_edid + '_Original', slTemp, 0);
for y := 0 to Pred(ElementCount(OTFTitems)) do
addToLeveledList(vanillaLevelList, LinksTo(elementbyindex(OTFTitems, y)), 1);
end
else
vanillaLevelList := elementbyindex(OTFTitems, 0);
end;
// Create masterlevellist if not already present
masterLevelList := MainRecordByEditorID(GroupBySignature(aPlugin, 'LVLI'), (OTFTrecord_edid + '_Master'));
{ Debug } if debugMsg and Assigned(masterLevelList) then
addMessage('[AddToOutfitAuto] Pre-existing masterLevelList := ' + EditorID(masterLevelList))
{ Debug } else
if debugMsg and not Assigned(masterLevelList) then
addMessage('[AddToOutfitAuto] Pre-existing masterLevelList not detected');
if not Assigned(masterLevelList) then
begin
slTemp.CommaText := '"Use All"';
masterLevelList := createLeveledList(aPlugin, OTFTrecord_edid + '_Master', slTemp, 0);
for y := 0 to 3 do
addToLeveledList(masterLevelList, vanillaLevelList, 1);
end;
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] if not LLcontains(' + EditorID(masterLevelList) + ', ' + EditorID(inputRecord) + ' ) := ' + BoolToStr(LLcontains(masterLevelList, inputRecord)) + ' then begin');
if not LLcontains(masterLevelList, inputRecord) then
begin
addToLeveledList(masterLevelList, inputRecord, 1);
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] addToLeveledList(' + EditorID(masterLevelList) + ', ' + EditorID(inputRecord) + ', 1);');
end;
end;
// This finishes restructuring the outfit so that new armor sets can be added as a whole set instead of piece by piece
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] if HasGroup(aPlugin, ''OTFT'') := ' + BoolToStr(HasGroup(aPlugin, 'OTFT')) + ' then');
OTFTcopy := MainRecordByEditorID(GroupBySignature(aPlugin, 'OTFT'), OTFTrecord_edid);
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] if not Assigned(OTFTcopy) := ' + BoolToStr(Assigned(OTFTcopy)) + ' then begin');
// If there is not already an override of OTFTcopy in aPlugin then create one
if not Assigned(OTFTcopy) then
begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] OTFTcopy := wbCopyElementToFile(' + OTFTrecord_edid + ', ' + GetFileName(aPlugin) + ', False, True)');
OTFTcopy := wbCopyElementToFile(OTFTrecord, aPlugin, false, true);
end;
debugMsg := false;
// End debugMsg Section
/// /////////////////////////////////////////////////////////////////// ASSEMBLE OTFT FROM VANILLA ENTRIES - RECORD IDENTIFICATION /////////////////////////////////////////////////////////////////////////////
// Begin debugMsg Section
debugMsg := false;
slEnchantedList.clear;
slBlackList.clear;
slLevelList.clear;
slItem.clear;
slTemp.clear;
// Check if OTFT contains LVLI
tempBoolean := false;
// Checks if OTFT has a LVLI to be processed
for x := 0 to Pred(ElementCount(ElementByPath(OTFTcopy, 'INAM'))) do
begin
if (Signature(LinksTo(elementbyindex(ElementByPath(OTFTcopy, 'INAM'), x))) = 'LVLI') then
begin
tempBoolean := true;
break;
end;
end;
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] ' + EditorID(OTFTcopy) + ' contains LVLI := ' + BoolToStr(tempBoolean));
// Get a complete list of all items and enchanted sets
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] Get a complete list of all items and enchanted sets');
if tempBoolean then
begin
for x := 0 to Pred(ElementCount(ElementByPath(OTFTcopy, 'INAM'))) do
begin
// Commonly used functions; This is just to reduce the number of complicated functions that are called (and therefore reduce processing time)
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] Commonly used functions');
tempRecord := WinningOverride(LinksTo(elementbyindex(ElementByPath(OTFTcopy, 'INAM'), x)));
Record_edid := EditorID(tempRecord);
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] tempRecord := '+EditorID(tempRecord));
tempBoolean := false;
// Check lists for an identical item
if slContains(slEnchantedList, Record_edid) or slContains(slLevelList, Record_edid) or slContains(slItem, Record_edid) then
tempBoolean := true;
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] ItemAlreadyAdded := '+BoolToStr(tempBoolean));
if not tempBoolean then
begin
if (Signature(tempRecord) = 'LVLI') then
begin
if ContainsText(EditorID(tempRecord), 'Ench') then
begin
if not slContains(slEnchantedList, Record_edid) then
begin
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] slEnchantedList.Add('+EditorID(tempRecord)+' );');
slEnchantedList.addObject(Record_edid, tempRecord);
end;
end else begin
if not slContains(slLevelList, Record_edid) then
begin
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] slTemp.Add(EditorID('+EditorID(tempRecord)+' ));');
slLevelList.addObject(Record_edid, tempRecord);
end;
end;
end else begin
if not slContains(slItem, Record_edid) then
begin
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] slItem.Add(EditorID('+EditorID(tempRecord)+' ));');
slItem.addObject(Record_edid, tempRecord);
end;
end;
end;
// Leveled lists are often nested multiple times. This 'while' loop adds all their entries to a single list
{ Debug } if debugMsg and (slLevelList.Count > 0) then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] Leveled lists are often nested multiple times. This ''while'' loop adds all their entries to a single list');
{ Debug } if debugMsg then
msgList('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] slLevelList := ', slLevelList, '');
while (slLevelList.Count > 0) do
begin
for y := 0 to Pred(LLec(ObjectToElement(slLevelList.Objects[0]))) do
begin
tempRecord := WinningOverride(LLelementbyindex(ObjectToElement(slLevelList.Objects[0]), y));
Record_edid := EditorID(tempRecord);
if not(Length(EditorID(tempRecord)) > 0) then
Continue;
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] tempRecord := '+Record_edid);
if (Signature(tempRecord) = 'LVLI') then
begin
if ContainsText(EditorID(tempRecord), 'Ench') then
begin
if not slContains(slEnchantedList, Record_edid) then
begin
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] slEnchantedList.Add(EditorID('+Record_edid+' ));');
slEnchantedList.addObject(Record_edid, tempRecord);
end;
end else begin
if not slContains(slLevelList, Record_edid) then
begin
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] slTempObject.Add(EditorID('+Record_edid+' ));');
slTempObject.addObject(Record_edid, tempRecord);
end;
end;
end else begin
if not slContains(slItem, Record_edid) then
begin
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] slItem.Add(EditorID('+Record_edid+' ));');
slItem.addObject(Record_edid, tempRecord);
end;
end;
end;
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] slLevelList.Delete('+slLevelList[0]+' );');
slLevelList.Delete(0);
if (slLevelList.Count = 0) then
begin
for z := 0 to slTempObject.Count - 1 do
begin
if not slContains(slLevelList, slTempObject[z]) then
begin
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] slLevelList.Add('+slTempObject[z]+' );');
slLevelList.addObject(slTempObject[z], ObjectToElement(slTempObject.Objects[z]));
end;
end;
slTempObject.clear;
end;
if (slLevelList.Count = -1) then
break;
end;
end;
// If there are enchanted lists, replace them with a 'template' record. For the sake of simplicity it will be replaced with the enchanted list later
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] If there are enchanted lists, make sure the original record is in the items list. For the sake of simplicity it will be replaced with the enchanted list later');
for x := 0 to slEnchantedList.Count - 1 do
begin
// Grab the template for the enchanted list. These are also nested often
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] tempRecord := ' + EditorID(WinningOverride(ObjectToElement(slEnchantedList.Objects[x]))));
tempRecord := WinningOverride(ObjectToElement(slEnchantedList.Objects[x]));
while (Signature(tempRecord) = 'LVLI') do
begin
tempRecord := LLelementbyindex(tempRecord, 0);
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] tempRecord := ' + EditorID(tempRecord));
end;
// Check the list for the template item
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] Check the list for the template item');
if not slContains(slItem, EditorID(GetEnchTemplate(tempRecord))) then
begin
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] slItem.Add('+EditorID(tempRecord)+' );');
slItem.addObject(EditorID(GetEnchTemplate(tempRecord)), GetEnchTemplate(tempRecord));
end;
end;
// This is the main section where similiar items are added to an outfit
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] This is the main section where similiar items are added to an outfit');
{ Debug } if debugMsg then
msgList('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] slItem := ', slItem, '');
for x := 0 to slItem.Count - 1 do
begin
slStringList.clear;
// Exclude entries already added to lists by this script
if slContains(slBlackList, slItem[x]) then
Continue
// Delete common junk words
slTemp.CommaText := 'Mask, Bracers, Armor, Helmet, Hood, Crown, Shield, Buckler, Cuirass, Greaves, Boots, Gloves, Gauntlets, Hood';
slStringList.CommaText := GetElementEditValues(WinningOverride(ObjectToElement(slItem.Objects[x])));
{ Debug } if debugMsg then
msgList('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] slStringList := ', slStringList, '');
for y := 0 to slTemp.Count - 1 do
if slContains(slStringList, slTemp[y]) then
slStringList.Delete(slStringList.IndexOf(slTemp[y]));
if slStringList.Count = 0 then
Continue;
slTempObject.clear;
// Search all slItem records for similiar words to the current record with decreasing levels of precision
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] Search all slItem records for similiar words to the current record with decreasing levels of precision');
{ Debug } if debugMsg then
msgList('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] slStringList := ', slStringList, '');
for y := 0 to slStringList.Count - 1 do
begin
commonString := nil;
for z := slStringList.Count - 1 downto 0 do
begin
commonString := Trim(commonString + ' ' + slStringList[z]);
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] [Decreasing Precision] CommonString := '+CommonString);
end;
for z := 0 to slItem.Count - 1 do
if ContainsText(GetElementEditValues(ObjectToElement(slItem.Objects[z])), commonString) then
if not(z = x) then
if not slContains(slTempObject, slItem[z]) then
slTempObject.addObject(slItem[z], slItem.Objects[z]);
if (slTempObject.Count > 1) then
break;
end;
if not(slTempObject.Count > 1) then
Continue;
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] Decreasing Precision Output := ' + commonString);
{ Debug } if debugMsg then
msgList('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] slTempObject := ', slTempObject, '');
debugMsg := false;
// End debugMsg section
/// /////////////////////////////////////////////////////////////////// ASSEMBLE OTFT FROM VANILLA ENTRIES - OUTFIT GENERATION /////////////////////////////////////////////////////////////////////////////
// Begin debugMsg section
debugMsg := false;
// Create and fill a level list for the outfit if one does not exist
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] Create and fill a level list for the outfit');
tempString := ('LLOutfit_' + RemoveSpaces(RemoveFileSuffix(GetFileName(GetFile(MasterOrSelf(tempRecord))))) + '_' + RemoveSpaces(commonString));
tempLevelList := MainRecordByEditorID(GroupBySignature(aPlugin, 'LVLI'), tempString);
{ Debug } if debugMsg and Assigned(tempLevelList) then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] tempLevelList already exists; tempLevelList := ' + EditorID(tempLevelList));
if not Assigned(tempLevelList) then
begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] tempLevelList unassigned; Creating ' + tempString);
slTemp.CommaText := '"Use All"';
tempLevelList := createLeveledList(aPlugin, tempString, slTemp, 0);
{ Debug } if debugMsg then
msgList('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] Begin vanilla outfit generation; slTempObject := ', slTempObject, '');
for y := 0 to slTempObject.Count - 1 do
begin
tempRecord := ObjectToElement(slTempObject.Objects[y]);
Record_edid := slTempObject[y];
// Check to see if the record was used in a previous loop
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] Check to see if the record was used in a previous loop');
if slContains(slBlackList, slTempObject[y]) then
Continue;
// Check if a subLevelList is needed
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] Check if a subLevelList is needed for ' + Record_edid);
sl1.clear;
sl2.clear;
tempBoolean := false;
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] slGetFlagValues('+slTempObject[y]+', '+GetElementType+' , ''First Person Flags''), sl1, False);');
slGetFlagValues(tempRecord, sl1, false);
{ Debug } if debugMsg then
msgList('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] sl1 := ', sl1, '');
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] Check for items that don''t use a primary or vanilla slot');
// Check for items that don't use a primary or vanilla slot; All of these items get subLevelLists in order to implement a percent chance none
sl2.CommaText := '30, 32, 33, 37, 39'; // 30 - Head, 32 - Body, 33 - Gauntlers, 37 - Feet, 39 - Shield
for z := 0 to sl2.Count - 1 do
if slContains(sl1, sl2[z]) then
tempBoolean := true;
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] Primary slot check := ' + BoolToStr(tempBoolean));
// Check for common primary slot keywords; This is primarily for to account for mods that change the slot layout of helmets for compatability reasons
sl2.CommaText := 'Boots, Helmet, Shield, Cuirass, Gauntlets, Shield, Hands, Head, Body, Gloves, Bracers, Ring, Robes, Hood, Mask';
for z := 0 to sl2.Count - 1 do
if ContainsText(Record_edid, sl2[z]) or ContainsText(GetElementEditValues(tempRecord), sl2[z]) then
tempBoolean := true;
tempBoolean := Flip(tempBoolean);
// Check for subLevelLists' slots
if not tempBoolean then
begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] Check for subLevelLists'' slots');
for z := 0 to Pred(LLec(tempLevelList)) do
begin
if (Signature(LLelementbyindex(tempLevelList, z)) = 'LVLI') then
begin
for a := 0 to sl1.Count - 1 do
begin
if ContainsText(EditorID(LLelementbyindex(tempLevelList, z)), sl1[a]) then
begin
tempBoolean := true;
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] subLevelList check := ' + BoolToStr(tempBoolean));
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] ContainsText(' + EditorID(LLelementbyindex(tempLevelList, z)) + ', ' + sl1[a] + ' )');
break;
end;
end;
end;
end;
end;
// Check for items that use the same slot
if not tempBoolean then
begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] Check for items that use the same slot');
for z := 0 to slTempObject.Count - 1 do
begin
if (z = y) then
Continue;
sl2.clear;
slGetFlagValues(tempRecord, sl2, false);
// {Debug} if debugMsg then msgList('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] sl1 := ', sl1, '');
// {Debug} if debugMsg then msgList('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] sl2 := ', sl2, '');
for a := 0 to sl1.Count - 1 do
begin
if slContains(sl2, sl1[a]) then
begin
tempBoolean := true;
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] same slot check := ' + BoolToStr(tempBoolean));
// {Debug} if debugMsg then msgList('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] slContains(',sl2, ', '+sl1[a]+' )');
break;
end;
end;
end;
end;
// Create subLevelList
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] Create subLevelList for ' + slTempObject[y] + ' := ' + BoolToStr(tempBoolean));
if tempBoolean then
begin
// Get pre-existing list or create a new one
String1 := nil;
for z := 0 to sl1.Count - 1 do
String1 := Trim(String1 + ' ' + sl1[z]);
// Check for pre-existing subLevelList
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] Check for pre-existing subLevelList');
subLevelList := MainRecordByEditorID(GroupBySignature(aPlugin, 'LVLI'), ('LLOutfit_' + RemoveSpaces(RemoveFileSuffix(GetFileName(GetFile(MasterOrSelf(tempRecord))))) + '_' + RemoveSpaces(commonString) + '_SubList_(BOD2: ' + String1 + ')'));
if Assigned(subLevelList) then
begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] Pre-existing sublist ' + EditorID(subLevelList) + ' detected; if not LLcontains(' + EditorID(tempLevelList) + ', ' + Record_edid + ' ) := ' + BoolToStr(LLcontains(tempLevelList, tempRecord)) + ' then begin');
if not LLcontains(subLevelList, tempRecord) then
begin
addToLeveledList(subLevelList, tempRecord, 1);
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] addToLeveledList(' + EditorID(tempLevelList) + ', ' + slTempObject[y] + ', 1);');
end;
// Blacklist used items
if not slContains(slBlackList, Record_edid) then
slBlackList.Add(Record_edid);
end;
// Create subLevelList if not already assigned
if not Assigned(subLevelList) then
begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] Creating new subLevelList');
slTemp.CommaText := '"Calculate from all levels <= player''s level", "Calculate for each item in count"';
subLevelList := createLeveledList(aPlugin, ('LLOutfit_' + RemoveSpaces(RemoveFileSuffix(GetFileName(GetFile((MasterOrSelf(tempRecord)))))) + '_' + RemoveSpaces(commonString) + '_SubList_(BOD2: ' + String1 + ')'), slTemp, 0);
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] addToLeveledList(' + EditorID(subLevelList) + ', ' + Record_edid + ', 1);');
addToLeveledList(subLevelList, tempRecord, 1);
// Items in non-primary or non-vanilla slots get an 80 percent chance none; This should include scarves, necklaces, etc.
sl2.clear;
sl2.CommaText := '30, 32, 33, 37, 39'; // 30 - Head, 32 - Body, 33 - Gauntlers, 37 - Feet, 39 - Shield
tempBoolean := false;
for z := 0 to sl2.Count - 1 do
if ContainsText(String1, sl2[z]) then
tempBoolean := true;
// Check for common primary slot keywords; This is primarily for to account for mods that change the slot layout of helmets for compatability reasons
sl2.CommaText := 'Boots, Helmet, Shield, Cuirass, Gauntlets, Shield, Hands, Head, Body, Gloves, Bracers, Ring, Robes, Hood, Mask';
for z := 0 to sl2.Count - 1 do
if ContainsText(Record_edid, sl2[z]) or ContainsText(GetElementEditValues(tempRecord), sl2[z]) then
tempBoolean := true;
if not tempBoolean then
SetElementNativeValues(subLevelList, 'LVLD', 80); // Percent chance none
// Blacklist used items
if not slContains(slBlackList, Record_edid) then
slBlackList.Add(Record_edid);
end;
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] Identify Records by BOD2');
// Identify Records by BOD2
for z := 0 to slTempObject.Count - 1 do
begin
tempelement := ObjectToElement(slTempObject.Objects[z]);
sl2.clear;
slGetFlagValues(tempelement, sl2, false);
tempInteger := 0;
for a := 0 to sl1.Count - 1 do
begin
for b := 0 to sl2.Count - 1 do
begin
if ContainsText(sl2[b], sl1[a]) then
begin
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] ContainsText('+sl2[b]+', '+sl1[a]+' )');
Inc(tempInteger);
end;
end;
end;
if (tempInteger = sl1.Count) then
begin
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries] if not LLcontains('+EditorID(subLevelList)+', '+slTempObject[z]+' ) := '+BoolToStr(LLcontains(subLevelList, tempElement))+' then begin');
if not LLcontains(subLevelList, tempelement) then
begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] addToLeveledList(' + EditorID(subLevelList) + ', ' + slTempObject[z] + ', 1);');
addToLeveledList(subLevelList, tempelement, 1);
end;
// Blacklist used items
if not slContains(slBlackList, slTempObject[z]) then
slBlackList.Add(slTempObject[z]);
end;
end;
// Check if the leveled list contains a template for an enchanted list
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] Check if the leveled list contains a template for an enchanted list');
for a := 0 to slEnchantedList.Count - 1 do
begin
for b := 0 to Pred(LLec(subLevelList)) do
begin
tempelement := ObjectToElement(slEnchantedList.Objects[a]);
if ElementExists(LLelementbyindex(tempelement, 0), 'CNAM') then
begin
if (EditorID(LinksTo(ElementBySignature(LLelementbyindex(tempelement, 0), 'CNAM'))) = EditorID(LLelementbyindex(subLevelList, b))) then
begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] LLreplace(' + EditorID(subLevelList) + ', ' + EditorID(LLelementbyindex(subLevelList, b)) + ', ' + slEnchantedList[a] + ' );');
if not LLcontains(tempLevelList, tempelement) then
LLreplace(tempLevelList, LLelementbyindex(subLevelList, b), tempelement);
end;
end
else
if ElementExists(LLelementbyindex(tempelement, 0), 'TNAM') then
begin
if (EditorID(LinksTo(ElementBySignature(LLelementbyindex(tempelement, 0), 'TNAM'))) = EditorID(LLelementbyindex(subLevelList, b))) then
begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] LLreplace(' + EditorID(subLevelList) + ', ' + EditorID(LLelementbyindex(subLevelList, b)) + ', ' + slEnchantedList[a] + ' );');
if not LLcontains(tempLevelList, tempelement) then
LLreplace(tempLevelList, LLelementbyindex(subLevelList, b), tempelement);
end;
end;
end;
end;
// Check if another leveled list also covers the same BOD2 parts
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] Check if another leveled list also covers the same BOD2 parts');
tempBoolean := false;
for z := 0 to Pred(LLec(tempLevelList)) do
begin
if (Signature(LLelementbyindex(tempLevelList, z)) = 'LVLI') then
begin
for a := 0 to sl1.Count - 1 do
begin
if ContainsText(EditorID(LLelementbyindex(tempLevelList, z)), sl1[a]) then
begin
String1 := StrPosCopy(EditorID(LLelementbyindex(tempLevelList, z)), '(', false);
String1 := StrPosCopy(String1, ')', true);
sl2.CommaText := String1;
if (sl1.Count < sl2.Count) then
begin
if not LLcontains(LLelementbyindex(tempLevelList, z), subLevelList) then
begin
addToLeveledList(LLelementbyindex(tempLevelList, z), subLevelList, 1);
tempBoolean := true;
// Removes duplicate elements in the leveled list one level above
// Example: A sublist for slot 40 is created and contains all items that occupy slot 40. There is already a list in tempLevelList for items with slot 40 and slot 42.
// This removes items that have slot bot slot 40 and slot 42, leaving only slot 40 items in the sublist
for b := 0 to Pred(LLec(tempLevelList)) do
if LLcontains(subLevelList, LLelementbyindex(tempLevelList, b)) then
LLremove(subLevelList, LLelementbyindex(tempLevelList, b));
// Sub-sublists don't need a percent chance none
if ElementExists(subLevelList, 'LVLD') then
Remove(ElementBySignature(subLevelList, 'LVLD'));
end;
end
else
if (sl1.Count > sl2.Count) then
begin
LLreplace(tempLevelList, LLelementbyindex(tempLevelList, z), subLevelList);
if not LLcontains(subLevelList, LLelementbyindex(tempLevelList, z)) then
begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] addToLeveledList(' + EditorID(subLevelList) + ', ' + EditorID(LLelementbyindex(tempLevelList, z)) + ', 1);');
addToLeveledList(subLevelList, LLelementbyindex(tempLevelList, z), 1);
tempBoolean := true;
// Removes duplicate elements in the leveled list one level above
for b := 0 to Pred(LLec(subLevelList)) do
if LLcontains(tempLevelList, LLelementbyindex(tempLevelList, b)) then
LLremove(tempLevelList, LLelementbyindex(tempLevelList, b));
// Sub-sublists don't need a percent chance none
if ElementExists(tempLevelList, 'LVLD') then
Remove(ElementBySignature(tempLevelList, 'LVLD'));
end;
end;
end;
end;
end;
end;
if not tempBoolean and not LLcontains(tempLevelList, subLevelList) then
addToLeveledList(tempLevelList, subLevelList, 1);
end else begin
if not LLcontains(tempLevelList, tempRecord) then
addToLeveledList(tempLevelList, tempRecord, 1);
// Blacklist used items
if not slContains(slBlackList, slTempObject[y]) then
slBlackList.Add(slTempObject[y]);
end;
end;
// Check if the leveled list contains a template for an enchanted list
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] Check if the leveled list contains a template for an enchanted list');
for z := 0 to slEnchantedList.Count - 1 do
begin
for a := 0 to Pred(LLec(tempLevelList)) do
begin
tempelement := ObjectToElement(slEnchantedList.Objects[z]);
if ElementExists(LLelementbyindex(tempelement, 0), 'CNAM') then
begin
if EditorID(LinksTo(ElementBySignature(LLelementbyindex(tempelement, 0), 'CNAM'))) = EditorID(LLelementbyindex(subLevelList, b)) then
begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] LLreplace(' + EditorID(tempLevelList) + ', ' + EditorID(LLelementbyindex(subLevelList, b)) + ', ' + slEnchantedList[z] + ' );');
if not LLcontains(tempLevelList, tempelement) then
LLreplace(tempLevelList, LLelementbyindex(subLevelList, b), tempelement);
end;
end
else
if ElementExists(LLelementbyindex(tempelement, 0), 'TNAM') then
begin
if EditorID(LinksTo(ElementBySignature(LLelementbyindex(tempelement, 0), 'TNAM'))) = EditorID(LLelementbyindex(subLevelList, b)) then
begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] LLreplace(' + EditorID(tempLevelList) + ', ' + EditorID(LLelementbyindex(subLevelList, b)) + ', ' + slEnchantedList[z] + ' );');
if not LLcontains(tempLevelList, tempelement) then
LLreplace(tempLevelList, LLelementbyindex(subLevelList, b), tempelement);
end;
end;
end;
end;
// Remove outfits with no primary vanilla BOD2 slots
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] Check ' + EditorID(tempLevelList) + ' for primary vanilla BOD2 slots');
tempBoolean := false;
for z := 0 to Pred(LLec(tempLevelList)) do
begin
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] LLelementbyindex(tempLevelList, z) := '+EditorID(LLelementbyindex(tempLevelList, z)));
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] Signature(LLelementbyindex(tempLevelList, z)) := '+Signature(LLelementbyindex(tempLevelList, z)));
if (Signature(LLelementbyindex(tempLevelList, z)) = 'LVLI') then
begin
// Check sublist
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] Check if ' + EditorID(tempLevelList) + ' sublist ' + EditorID(LLelementbyindex(tempLevelList, z)) + ' is a script sublist');
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] if ContainsText(EditorID('+EditorID(LLelementbyindex(tempLevelList, z))+', ''BOD2'') then begin');
if ContainsText(EditorID(LLelementbyindex(tempLevelList, z)), 'BOD2') or ContainsText(EditorID(LLelementbyindex(tempLevelList, z)), 'Ench') then
begin
sl1.clear;
tempString := Trim(StrPosCopy(EditorID(LLelementbyindex(tempLevelList, z)), ':', false));
tempString := Trim(StrPosCopy(tempString, ')', true));
sl1.CommaText := tempString;
sl2.clear;
sl2.CommaText := '30, 32, 33, 37, 39'; // 30 - Head, 32 - Body, 33 - Gauntlers, 37 - Feet, 39 - Shield
// This 'if' prevents tempLevelList deletion if the BOD2 list doesn't generate correctly
if (sl1.Count > 0) then
begin
for a := 0 to sl1.Count - 1 do
if slContains(sl2, sl1[a]) then
tempBoolean := true;
end else begin
addMessage('[ERROR] ' + EditorID(LLelementbyindex(tempLevelList, z)) + ' expected BOD2 did not generate correctly - [AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation]');
tempBoolean := true;
end;
end;
end else begin
// Check normal item
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] Check ' + EditorID(tempLevelList) + ' for a normal item');
sl1.clear;
slGetFlagValues(LLelementbyindex(tempLevelList, z), sl1, false);
sl2.CommaText := '30, 32, 33, 37, 39'; // 30 - Head, 32 - Body, 33 - Gauntlers, 37 - Feet, 39 - Shield
// This 'if' prevents tempLevelList deletion if the BOD2 list doesn't generate correctly
if (sl1.Count > 0) then
begin
for a := 0 to sl1.Count - 1 do
if slContains(sl2, sl1[a]) then
tempBoolean := true;
end else begin
addMessage('[ERROR] ' + EditorID(LLelementbyindex(tempLevelList, z)) + ' expected BOD2 did not generate correctly - [AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation]');
tempBoolean := true;
end;
end;
end;
if not tempBoolean then
begin
sl1.clear;
{ Debug } if debugMsg then
for z := 0 to Pred(LLec(tempLevelList)) do
sl1.Add(EditorID(LLelementbyindex(tempLevelList, z)));
{ Debug } if debugMsg then
msgList('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] ' + EditorID(tempLevelList) + ' := ', sl1, '');
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] Remove(' + EditorID(tempLevelList) + ' )');
Remove(tempLevelList);
Continue;
end else begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] ' + EditorID(tempLevelList) + ' does contain primary vanilla BOD2 slots');
end;
end;
debugMsg := false;
// End debugMsg section
/// /////////////////////////////////////////////////////////////////// ASSEMBLE OTFT FROM VANILLA ENTRIES - OUTFIT VARIATIONS /////////////////////////////////////////////////////////////////////////////
// Begin debugMsg section
debugMsg := false;
if Assigned(tempLevelList) then
begin
// If an outfit Master list requires additional BOD2 slots, make a variant of tempLevelList
for z := 0 to Pred(ElementCount(ElementBySignature(OTFTcopy, 'INAM'))) do
begin
sl1.clear;
sl2.clear;
tempRecord := WinningOverride(LinksTo(elementbyindex(ElementByPath(OTFTcopy, 'INAM'), z)));
// Get a list of expected BOD2 slots
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Variations] Get a list of expected BOD2 slots for ' + EditorID(tempRecord));
if (Signature(tempRecord) = 'LVLI') then
begin
for a := 0 to Pred(LLec(tempRecord)) do
begin
if (Signature(LLelementbyindex(tempRecord, a)) = 'LVLI') then
begin
sl2.addObject(EditorID(LLelementbyindex(tempRecord, z)), LLelementbyindex(tempRecord, z));
end else begin
slGetFlagValues(LLelementbyindex(tempRecord, a), sl1, false);
end;
end;
// This is a recursive check for nested leveled lists
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Variations] This is a recursive check for nested leveled lists');
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Variations] sl2.Count := ' + IntToStr(sl2.Count));
if (sl2.Count > 0) then
begin
while (sl2.Count > 0) do
begin
tempelement := ObjectToElement(sl2.Objects[0]);
if (LLec(tempelement) = 0) then
begin
sl2.Delete(0);
Continue;
end;
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Variations] for a := 0 to '+IntToStr(Pred(LLec(tempElement)))+' do begin');
for a := 0 to Pred(LLec(tempelement)) do
begin
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Variations] if ('+Signature(LLelementbyindex(tempElement, a))+' = ''LVLI'') then begin');
if (Signature(LLelementbyindex(tempelement, a)) = 'LVLI') then
begin
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Variations] if not slContains(sl1, '+EditorID(LLelementbyindex(tempElement, a))+' ) then');
if not slContains(sl1, EditorID(LLelementbyindex(tempelement, a))) then
begin
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Variations] sl2.Add('+EditorID(LLelementbyindex(tempElement, a))+' );');
sl2.addObject(EditorID(LLelementbyindex(tempelement, a)), LLelementbyindex(tempelement, a));
end;
end else begin
slGetFlagValues(LLelementbyindex(tempelement, a), sl1, false);
end;
end;
sl2.Delete(0);
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Variations] sl2.Delete('+sl2[0]+' )');
end;
end;
end else begin
sl1.clear;
slGetFlagValues(tempRecord, sl1, false);
end;
// Check to see if the outfit contains any item or sublist covering these BOD2 slots
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Variations] Check to see if the outfit contains any item or sublist covering these BOD2 slots');
if (sl1.Count > 0) then
begin
tempBoolean := false;
for z := 0 to Pred(LLec(tempLevelList)) do
begin
if (Signature(LLelementbyindex(tempLevelList, z)) = 'LVLI') then
begin
// Check sublist
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Variations] Check if ' + EditorID(tempLevelList) + ' sublist ' + EditorID(LLelementbyindex(tempLevelList, z)) + ' is a script sublist');
if ContainsText(EditorID(LLelementbyindex(tempLevelList, z)), 'BOD2') then
begin
sl2.clear;
tempString := Trim(StrPosCopy(EditorID(LLelementbyindex(tempLevelList, z)), ':', false));
tempString := Trim(StrPosCopy(tempString, ')', true));
sl2.CommaText := tempString;
// This 'if' prevents tempLevelList deletion if the BOD2 list doesn't generate correctly
if (sl1.Count > 0) then
begin
for a := 0 to sl1.Count - 1 do
if slContains(sl2, sl1[a]) then
tempBoolean := true;
end else begin
addMessage('[ERROR] ' + EditorID(tempRecord) + ' expected BOD2 did not generate correctly - [AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Variations]');
tempBoolean := true;
end;
{ Debug } if debugMsg then
msgList('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Variations] Check ' + EditorID(LLelementbyindex(tempLevelList, z)) + ' sublist for ', sl1, ' := ' + BoolToStr(tempBoolean));
// Check enchanted list
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Variations] Check if ' + EditorID(LLelementbyindex(tempLevelList, z)) + ' is an enchanted list');
end;
end else begin
// Check normal item
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Variations] Check normal item');
sl2.clear;
slGetFlagValues(LLelementbyindex(tempLevelList, z), sl2, false);
{ Debug } if debugMsg then
msgList('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Variations] Checking for ' + EditorID(tempRecord) + ' BOD2 sl1 := ', sl1, '');
{ Debug } if debugMsg then
msgList('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Variations] Checking for ' + EditorID(LLelementbyindex(tempLevelList, z)) + ' BOD2 sl2 := ', sl2, '');
// This 'if' prevents tempLevelList deletion if the BOD2 list doesn't generate correctly
if (sl1.Count > 0) then
begin
for a := 0 to sl1.Count - 1 do
if slContains(sl2, sl1[a]) then
tempBoolean := true;
end else begin
addMessage('[ERROR] ' + EditorID(tempRecord) + ' expected BOD2 did not generate correctly - [AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Variations]');
tempBoolean := true;
end;
end;
end;
// If the generated outfit does not cover all the BOD2 slots the master outfit contains, create a copy and use that instead
// Example: Leather outfits often generate with only a cuirass.
// In this case, if an outfit consists of LItemBanditHelmet, LItemBanditCuirass, and LItemBanditBoots (a common setup)
// a variant of the leveled list with just the leather cuirass would generate containing the leather cuirass, LItemBanditHelmet, and LItemBanditBoots
if not tempBoolean then
begin
// {Debug} if debugMsg then addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Variations] if StrEndsWith('+EditorID(tempLevelList)+', '+EditorID(OTFTcopy)+' ) then begin');
if StrEndsWith(EditorID(tempLevelList), EditorID(OTFTcopy)) then
begin
subLevelList := tempLevelList
end else begin
subLevelList := MainRecordByEditorID(GroupBySignature(aPlugin, 'LVLI'), EditorID(tempLevelList) + '_' + EditorID(OTFTcopy));
end;
if not Assigned(subLevelList) then
begin
subLevelList := wbCopyElementToFile(tempLevelList, aPlugin, true, true);
SetElementEditValues(subLevelList, 'EDID', EditorID(tempLevelList) + '_' + EditorID(OTFTcopy));
end;
if Assigned(subLevelList) then
tempLevelList := subLevelList;
if not LLcontains(tempLevelList, tempRecord) then
addToLeveledList(tempLevelList, tempRecord, 1);
end;
end;
end;
// Add tempLevelList to masterLevelList if it is not already present
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] if not LLcontains(' + EditorID(masterLevelList) + ', ' + EditorID(tempLevelList) + ' ) := ' + BoolToStr(LLcontains(masterLevelList, tempLevelList)) + ' then begin');
if not LLcontains(masterLevelList, tempLevelList) then
begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Assemble OTFT From Vanilla Entries - Outfit Generation] addToLeveledList(' + EditorID(masterLevelList) + ', ' + EditorID(tempLevelList) + ', 1);');
addToLeveledList(masterLevelList, tempLevelList, 1);
end;
end;
// Blacklist used items
if not slContains(slBlackList, slItem[x]) then
slBlackList.Add(slItem[x]);
end;
end;
debugMsg := false;
// End debugMsg Section
/// /////////////////////////////////////////////////////////////////// SPECIFIC OTFT TYPES - PRE-CHECK ////////////////////////////////////////////////////////////////////////////////
// Begin debugMsg Section
debugMsg := false;
// Checks for integer-keyword pairs (e.g. Shield20 becomes 20=Shield)
// This checks each OTFT item for an integer-keyword pair (e.g. Shield20 becomes 20=Shield)
slTemp.clear;
slpair.clear;
slTemp.CommaText := 'Bracers, Helmet, Hood, Crown, Shield, Buckler, Cuirass, Greaves, Boots, Gloves, Gauntlets';
tempBoolean := false;
for x := 0 to Pred(ElementCount(ElementByPath(OTFTcopy, 'INAM'))) do
begin
tempRecord := LinksTo(elementbyindex(ElementByPath(OTFTcopy, 'INAM'), x)); { Debug }
if debugMsg then
addMessage('[AddToOutfitAuto] [Pre-Check] tempRecord := ' + EditorID(tempRecord));
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Pre-Check] if Signature(' + EditorID(tempRecord) + ' ) := ' + Signature(tempRecord) + ' = ''LVLI'' then begin');
if (Signature(tempRecord) = 'LVLI') then
begin { Debug }
if debugMsg then
addMessage('[AddToOutfitAuto] [Pre-Check] if (IntWithinStr(EditorID(tempRecord)) := ' + IntToStr(IntWithinStr(EditorID(tempRecord))) + ' ) <> -1) then begin');
if (IntWithinStr(EditorID(tempRecord)) <> -1) then
begin
for y := 0 to slTemp.Count - 1 do
begin { Debug }
if debugMsg then
addMessage('[AddToOutfitAuto] [Pre-Check] if ContainsText(' + EditorID(tempRecord) + ', ' + slTemp[y] + ' ) then begin');
if ContainsText(EditorID(tempRecord), slTemp[y]) then
begin
for z := 0 to slpair.Count - 1 do
if slpair.Names[z] = slTemp[y] then
tempBoolean := true;
if not tempBoolean then
begin
slpair.Add(slAddValue(IntToStr(IntWithinStr(EditorID(tempRecord))), slTemp[y]));
{ Debug } if debugMsg then
msgList('[AddToOutfitAuto] [Pre-Check] slpair := ', slpair, '');
end;
end;
end;
end;
end;
end;
// This checks the OTFT EditorID for an integer-keyword pair
if (IntWithinStr(EditorID(OTFTcopy)) <> -1) then
begin
for y := 0 to slTemp.Count - 1 do
begin { Debug }
if debugMsg then
addMessage('[AddToOutfitAuto] [Pre-Check] if (IntWithinStr(EditorID(OTFTcopy) := ' + IntToStr(IntWithinStr(EditorID(OTFTcopy))) + ' <> -1) then begin');
if (IntWithinStr(EditorID(OTFTcopy)) <> -1) then
begin { Debug }
if debugMsg then
addMessage('[AddToOutfitAuto] [Pre-Check] if ContainsText(' + EditorID(OTFTcopy) + ', ' + slTemp[y] + ' ) then begin');
if ContainsText(EditorID(OTFTcopy), slTemp[y]) then
begin
for z := 0 to slpair.Count - 1 do
if slpair.Names[z] = slTemp[y] then
tempBoolean := true;
if not tempBoolean then
begin
slpair.Add(slAddValue(IntToStr(IntWithinStr(EditorID(OTFTcopy))), slTemp[y]));
{ Debug } if debugMsg then
msgList('[AddToOutfitAuto] [Pre-Check] slpair := ', slpair, '');
end;
end;
end;
end;
end;
/// /////////////////////////////////////////////////////////////////// SPECIFIC OTFT TYPES - INTEGER ////////////////////////////////////////////////////////////////////////////////
if (slpair.Count > 0) then
begin { Debug }
if debugMsg then
msgList('[AddToOutfitAuto] [Integer] slpair := ', slpair, '');
// This is checking the input level list for keywords similiar to the identified keyword
// This is ghetto fuzzy logic. Example: If the pre-check identifies 'Gauntlets' then this
// section would check the input record for entries containing 'Gauntlets, Gloves';
tempBoolean := false;
{ Debug } if debugMsg then
msgList('[AddToOutfitAuto] [Integer] slpair := ', slpair, '');
for x := 0 to slpair.Count - 1 do
begin
{ Debug } if debugMsg then
msgList('[AddToOutfitAuto] [Integer] slFuzzyItem(' + slpair.Names[x] + ', ', slTemp, ' )');
// Check for inputRecord for all keywords related to the keyword detected in the OTFT 'EditorID' or 'INAM' items
slTemp.clear;
slFuzzyItem(slpair.Names[x], slTemp); { Debug }
if debugMsg and (x = 0) then
msgList('[AddToOutfitAuto] [Integer] slTemp := ', slTemp, '');
tempLevelList := nil;
for y := 0 to Pred(LLec(inputRecord)) do
begin
tempRecord := LLelementbyindex(inputRecord, y); { Debug }
if debugMsg then
addMessage('[AddToOutfitAuto] [Integer] tempRecord := ' + EditorID(tempRecord));
for z := 0 to slTemp.Count - 1 do
begin { Debug }
if debugMsg then
addMessage('[AddToOutfitAuto] [Integer] if ContainsText(' + EditorID(tempRecord) + ', ' + slTemp[z] + ' ) or ContainsText(' + GetElementEditValues(tempRecord) + ', ' + slTemp[z] + ' ) or HasKeyword(' + EditorID(tempRecord) + ', Armor' + slTemp[z] + ' ) or HasKeyword(' + EditorID(tempRecord) + ', Clothing' + slTemp[z] + ' ) then begin');
if ContainsText(EditorID(tempRecord), slTemp[z]) or ContainsText(GetElementEditValues(tempRecord), slTemp[z]) or HasKeyword(tempRecord, 'Armor' + slTemp[z]) or HasKeyword(tempRecord, 'Clothing' + slTemp[z]) then
begin
// If more than one integer-keyword pair is detected we need to account for both (e.g. Shield20Helmet50
tempString := nil;
for a := 0 to slpair.Count - 1 do
tempString := tempString + slpair.Names[a] + slpair.ValueFromIndex[a]; { Debug }
if debugMsg then
addMessage('[AddToOutfitAuto] [Integer] tempString := ' + tempString);
// Check if aPlugin already has an identically named variant of inputRecord
// The result needs to be true for any combination of slpair entries
// Example: Either Gauntlets50Helmet50 or Helmet50Gauntlets50 will return true
if not Assigned(tempLevelList) then
begin
for a := 0 to Pred(ElementCount(GroupBySignature(aPlugin, 'LVLI'))) do
begin
tempInteger := 0;
for b := 0 to slpair.Count - 1 do
if ContainsText(EditorID(elementbyindex(GroupBySignature(aPlugin, 'LVLI'), a)), EditorID(inputRecord)) and ContainsText(EditorID(elementbyindex(GroupBySignature(aPlugin, 'LVLI'), a)), slpair.Names[b] + slpair.ValueFromIndex[b]) then
Inc(tempInteger);
if (tempInteger = slpair.Count) then
begin { Debug }
if debugMsg then
addMessage('[AddToOutfitAuto] [Integer] Pre-existing variant of inputRecord detected: ' + EditorID(elementbyindex(GroupBySignature(aPlugin, 'LVLI'), a)));
tempLevelList := elementbyindex(GroupBySignature(aPlugin, 'LVLI'), a);
break;
end;
end;
end
else
if debugMsg then
addMessage('[AddToOutfitAuto] [Integer] tempLevelList already assigned');
// Create a new level list if a pre-existing one is not detected; This is a variant of inputRecord, NOT the sublist
if not Assigned(tempLevelList) then
begin { Debug }
if debugMsg then
addMessage('[AddToOutfitAuto] [Integer] ' + EditorID(inputRecord) + ' variant not detected; Creating ' + EditorID(inputRecord) + '_' + tempString + ' level list');
tempLevelList := wbCopyElementToFile(inputRecord, aPlugin, true, true);
SetElementEditValues(tempLevelList, 'EDID', EditorID(inputRecord) + '_' + tempString);
end;
// Check if aPlugin already has an identically named sublist
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Integer] Checking for pre-existing ' + (EditorID(inputRecord) + '_Sublist_' + slpair.Names[x] + slpair.ValueFromIndex[x]) + ' subLevelList');
subLevelList := MainRecordByEditorID(GroupBySignature(aPlugin, 'LVLI'), (EditorID(inputRecord) + '_SubList_' + slpair.Names[x] + slpair.ValueFromIndex[x]));
// Add subLevelList to tempLevelList if not already added
if Assigned(subLevelList) then
begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Integer] if not LLcontains(' + EditorID(tempLevelList) + ', ' + EditorID(subLevelList) + ' ) := ' + BoolToStr(LLcontains(tempLevelList, subLevelList)) + ' then begin');
if not LLcontains(tempLevelList, subLevelList) then
begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Integer] addToLeveledList(' + EditorID(tempLevelList) + ', ' + EditorID(subLevelList) + ', 1);');
addToLeveledList(tempLevelList, subLevelList, 1);
end;
end;
// Create a new sub level list if a pre-existing one is not detected
if not Assigned(subLevelList) then
begin
slTemp.CommaText := '"Use All"';
subLevelList := createLeveledList(aPlugin, (EditorID(inputRecord) + '_SubList_' + slpair.Names[x] + slpair.ValueFromIndex[x]), slTemp, (100 - StrToInt(slpair.ValueFromIndex[x])));
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Integer] addToLeveledList(' + EditorID(subLevelList) + ', ' + EditorID(tempRecord) + ', 1);');
addToLeveledList(subLevelList, tempRecord, 1);
end;
if Assigned(subLevelList) then
begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Integer] if not LLcontains(' + EditorID(tempLevelList) + ', ' + EditorID(subLevelList) + ' ) := ' + BoolToStr(LLcontains(tempLevelList, subLevelList)) + ' then begin');
if not LLcontains(tempLevelList, subLevelList) then
begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Integer] LLreplace(' + EditorID(tempLevelList) + ', ' + EditorID(tempRecord) + ', ' + EditorID(subLevelList) + ' );');
LLreplace(tempLevelList, tempRecord, subLevelList);
end;
end;
end;
end;
end;
end;
OTFTitem := RefreshList(OTFTcopy, 'INAM'); { Debug }
if debugMsg then
addMessage('[AddToOutfitAuto] [Integer] Refreshing ' + EditorID(OTFTcopy) + ' ''INAM'' Element');
// Add the finished variant of the inputRecord level list to the OTFT
if Assigned(tempLevelList) then
begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Integer] LLreplace(' + EditorID(masterLevelList) + ', ' + EditorID(tempLevelList) + ', 1);');
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Integer] SetEditValue(' + GetEditValue(elementbyindex(ElementByPath(OTFTcopy, 'INAM'), 0)) + ', ' + ShortName(masterLevelList) + ');');
LLreplace(masterLevelList, inputRecord, tempLevelList);
SetEditValue(OTFTitem, ShortName(masterLevelList)); { Debug }
if debugMsg then
addMessage('[AddToOutfitAuto] [Integer] SetEditValue(' + GetEditValue(OTFTitem) + ', ShortName(' + EditorID(tempLevelList) + ' ) := ' + ShortName(tempLevelList) + ' )');
end
else
addMessage('[AddToOutfitAuto] [ERROR] tempLevelList output not generated for: ' + EditorID(OTFTcopy));
/// /////////////////////////////////////////////////////////////////// SPECIFIC OTFT TYPES - NO/WITHOUT ////////////////////////////////////////////////////////////////////////////////
end
else
if ContainsText(EditorID(OTFTcopy), 'No') or ContainsText(EditorID(OTFTcopy), 'without') then
begin
// Check for a keyword with the OTFT 'EDID'
// Get a list of all keywords related to the keyword detected
slTemp.CommaText := 'Mask, Bracers, Helmet, Hood, Crown, Shield, Buckler, Cuirass, Greaves, Boots, Gloves, Gauntlets';
for x := 0 to slTemp.Count - 1 do
begin
if ContainsText(EditorID(OTFTcopy), slTemp[x]) then
begin
tempString := slTemp[x];
slFuzzyItem(slTemp[x], slTemp);
break;
end;
end;
// Checking GetElementEditValues, EditorID, and Keywords for relevant item types
OTFTitem := RefreshList(OTFTcopy, 'INAM');
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [No/Without] No/Without OTFT detected');
for y := 0 to Pred(LLec(inputRecord)) do
begin
LLentry := LLelementbyindex(inputRecord, y);
tempBoolean := false;
for z := 0 to slTemp.Count - 1 do
begin
if ContainsText(EditorID(LLentry), slTemp[z]) then
tempBoolean := true;
if ContainsText(GetElementEditValues(LLentry), slTemp[z]) then
tempBoolean := true;
if HasKeyword(LLentry, 'Armor' + slTemp[z]) or HasKeyword(LLentry, 'Clothing' + slTemp[z]) then
tempBoolean := true;
end;
if tempBoolean then
begin
tempInteger := y;
break;
end;
end;
if tempBoolean then
begin
tempLevelList := wbCopyElementToFile(inputRecord, aPlugin, true, true);
SetElementEditValues(tempLevelList, 'EDID', EditorID(inputRecord) + '_No' + tempString);
Remove(elementbyindex(ElementByPath(inputRecord, 'Leveled List Entries'), tempInteger));
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [No/Without] addToLeveledList(' + EditorID(masterLevelList) + ', ' + EditorID(tempLevelList) + ', 1);');
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [No/Without] SetEditValue(' + GetEditValue(elementbyindex(ElementByPath(OTFTcopy, 'INAM'), 0)) + ', ' + ShortName(masterLevelList) + ');');
addToLeveledList(masterLevelList, tempLevelList, 1);
SetEditValue(OTFTitem, ShortName(masterLevelList));
end else begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [No/Without] SetEditValue(' + GetEditValue(elementbyindex(ElementByPath(OTFTcopy, 'INAM'), 0)) + ', ' + ShortName(masterLevelList) + ');');
SetEditValue(OTFTitem, ShortName(masterLevelList));
end;
/// /////////////////////////////////////////////////////////////////// SPECIFIC OTFT TYPES - SIMPLE ////////////////////////////////////////////////////////////////////////////////
end
else
if ContainsText(EditorID(OTFTcopy), 'Simple') then
begin
OTFTitem := RefreshList(OTFTcopy, 'INAM');
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Simple] Simple OTFT detected');
tempLevelList := wbCopyElementToFile(inputRecord, aPlugin, true, true);
SetElementEditValues(tempLevelList, 'EDID', EditorID(inputRecord) + '_Simple');
Remove(ElementByPath(tempLevelList, 'Leveled List Entries'));
Add(tempLevelList, 'Leveled List Entries', true);
RemoveInvalidEntries(tempLevelList);
// Checking GetElementEditValues, EditorID, and Keywords for relevant item types
for y := 0 to Pred(LLec(inputRecord)) do
begin
LLentry := LLelementbyindex(inputRecord, y);
slTemp.CommaText := 'Helm, Hood, Head, Boots, Shoes, Feet';
tempBoolean := false;
for z := 0 to slTemp.Count - 1 do
begin
if ContainsText(EditorID(LLentry), slTemp[z]) then
tempBoolean := true;
if ContainsText(GetElementEditValues(LLentry), slTemp[z]) then
tempBoolean := true;
if HasKeyword(LLentry, 'Armor' + slTemp[z]) or HasKeyword(LLentry, 'Clothing' + slTemp[z]) then
tempBoolean := true;
end;
if tempBoolean then
addToLeveledList(tempLevelList, LLentry, 1);
end;
end
else
if ContainsText(EditorID(OTFTrecord), 'Bandit') then
begin
OTFTitem := RefreshList(OTFTcopy, 'INAM');
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] Bandit OTFT detected');
// Checking GetElementEditValues, EDID, and Keywords for relevant item types
for y := 0 to Pred(LLec(inputRecord)) do
begin
LLentry := LLelementbyindex(inputRecord, y);
slTemp.CommaText := 'Gloves, Gauntlets, Hands';
tempBoolean := false;
for z := 0 to slTemp.Count - 1 do
begin
if ContainsText(EditorID(LLentry), slTemp[z]) then
tempBoolean := true;
if ContainsText(GetElementEditValues(LLentry), slTemp[z]) then
tempBoolean := true;
if HasKeyword(LLentry, 'Armor' + slTemp[z]) or HasKeyword(LLentry, 'Clothing' + slTemp[z]) then
tempBoolean := true;
end;
if tempBoolean then
begin
tempInteger := y;
break;
end;
end;
if tempBoolean then
begin
tempLevelList := wbCopyElementToFile(inputRecord, aPlugin, true, true);
SetElementEditValues(tempLevelList, 'EDID', EditorID(inputRecord) + '_Gauntlets50');
subLevelList := MainRecordByEditorID(GroupBySignature(aPlugin, 'LVLI'), EditorID(inputRecord) + '_SubList_Gauntlets50');
if not Assigned(subLevelList) then
slTemp.CommaText := '"Use All"';
subLevelList := createLeveledList(aPlugin, EditorID(inputRecord) + '_SubList_Gauntlets50', slTemp, 50);
if not LLcontains(subLevelList, LLelementbyindex(inputRecord, tempInteger)) then
begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] addToLeveledList(' + EditorID(subLevelList) + ', ' + EditorID(LLelementbyindex(inputRecord, tempInteger)) + ', 1);');
addToLeveledList(subLevelList, LLelementbyindex(inputRecord, tempInteger), 1);
end;
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Simple] addToLeveledList(' + EditorID(masterLevelList) + ', ' + EditorID(tempLevelList) + ', 1);');
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Simple] SetEditValue(' + GetEditValue(elementbyindex(ElementByPath(OTFTcopy, 'INAM'), 0)) + ', ' + ShortName(masterLevelList) + ');');
addToLeveledList(masterLevelList, tempLevelList, 1);
SetEditValue(OTFTitem, ShortName(masterLevelList));
end else begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Simple] SetEditValue(' + GetEditValue(elementbyindex(ElementByPath(OTFTcopy, 'INAM'), 0)) + ', ' + ShortName(masterLevelList) + ');');
SetEditValue(OTFTitem, ShortName(masterLevelList));
end;
/// /////////////////////////////////////////////////////////////////// SPECIFIC OTFT TYPES - OTHER ////////////////////////////////////////////////////////////////////////////////
end else begin
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Other] Other OTFT detected; SetEditValue(' + GetEditValue(elementbyindex(ElementByPath(OTFTcopy, 'INAM'), 0)) + ', ' + ShortName(masterLevelList) + ' );');
slTemp.CommaText := 'Shield, Buckler';
tempBoolean := false;
for y := 0 to Pred(ElementCount(ElementByPath(OTFTrecord, 'INAM'))) do
begin
for z := 0 to slTemp.Count - 1 do
begin
if ContainsText(EditorID(LLentry), slTemp[z]) then
tempBoolean := true;
if ContainsText(GetElementEditValues(LLentry), slTemp[z]) then
tempBoolean := true;
if HasKeyword(LLentry, 'Armor' + slTemp[z]) or HasKeyword(LLentry, 'Clothing' + slTemp[z]) then
tempBoolean := true;
end;
if tempBoolean then
tempInteger := y;
end;
OTFTitem := RefreshList(OTFTcopy, 'INAM');
if tempBoolean then
begin
tempBoolean := false;
for y := 0 to Pred(LLec(inputRecord)) do
begin
tempRecord := LLelementbyindex(inputRecord, y);
for z := 0 to slTemp.Count - 1 do
begin
if ContainsText(EditorID(LLentry), slTemp[z]) then
tempBoolean := true;
if ContainsText(GetElementEditValues(LLentry), slTemp[z]) then
tempBoolean := true;
if HasKeyword(LLentry, 'Armor' + slTemp[z]) or HasKeyword(LLentry, 'Clothing' + slTemp[z]) then
tempBoolean := true;
end;
end;
if tempBoolean then
begin
tempLevelList := wbCopyElementToFile(inputRecord, aPlugin, true, true);
SetElementEditValues(tempLevelList, 'EDID', EditorID(inputRecord) + '_NoShield');
RemoveElement(elementbyindex(ElementByPath(tempLevelList, 'Leveled List Entries'), tempInteger));
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Other] addToLeveledList(' + EditorID(masterLevelList) + ', ' + EditorID(tempLevelList) + ', 1);');
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] [Other] SetEditValue(' + GetEditValue(elementbyindex(ElementByPath(OTFTcopy, 'INAM'), 0)) + ', ' + ShortName(masterLevelList) + ' );');
addToLeveledList(masterLevelList, tempLevelList, 1);
SetEditValue(OTFTitem, ShortName(masterLevelList));
end
else
SetEditValue(OTFTitem, ShortName(masterLevelList));
end
else
SetEditValue(OTFTitem, ShortName(masterLevelList));
end;
end;
// Finalize
if Assigned(slEnchantedList) then
slEnchantedList.Free;
if Assigned(slStringList) then
slStringList.Free;
if Assigned(slTempObject) then
slTempObject.Free;
if Assigned(slBlackList) then
slBlackList.Free;
if Assigned(slLevelList) then
slLevelList.Free;
if Assigned(slOutfit) then
slOutfit.Free;
if Assigned(slItem) then
slItem.Free;
if Assigned(slTemp) then
slTemp.Free;
if Assigned(slpair) then
slpair.Free;
if Assigned(sl1) then
sl1.Free;
if Assigned(sl2) then
sl2.Free;
debugMsg := false;
// End debugMsg Section
end;
// Find the type of Item
function ItemKeyword(inputRecord: IInterface): string;
var
KWDAentries, KWDAkeyword: IInterface;
debugMsg : boolean;
slTemp : TStringList;
i : integer;
begin
// Begin debugMsg section
debugMsg := false;
// Initialize
if not Assigned(slTemp) then
slTemp := TStringList.Create
else
slTemp.clear;
// Function
slTemp.CommaText := 'ArmorHelmet, ArmorCuirass, ArmorGauntlets, ArmorBoots, ArmorShield, ClothingHead, ClothingBody, ClothingHands, ClothingFeet, ClothingCirclet, ClothingRing, ClothingNecklace, WeapTypeBattleaxe, WeapTypeBow, WeapTypeDagger, WeapTypeGreatsword, WeapTypeMace, WeapTypeSword, WeapTypeWarAxe, WeapTypeWarhammer, VendorItemArrow';
{ Debug } if debugMsg then
for i := 0 to slTemp.Count - 1 do
addMessage('[ItemKeyword] ' + slTemp[i]);
KWDAentries := ElementByPath(inputRecord, 'KWDA'); { Debug }
if debugMsg then
addMessage('[ItemKeyword] Pred(ElementCount(KWDAentries)) :=' + IntToStr(Pred(ElementCount(KWDAentries))));
for i := 0 to Pred(ElementCount(KWDAentries)) do
begin { Debug }
if debugMsg then
addMessage('[ItemKeyword] LinksTo(elementbyindex(KWDAentries, i)) :=' + EditorID(LinksTo(elementbyindex(KWDAentries, i))));
KWDAkeyword := LinksTo(elementbyindex(KWDAentries, i)); { Debug }
if debugMsg then
addMessage('[ItemKeyword] slTemp.Count-1 :=' + IntToStr(slTemp.Count - 1));
for i := 0 to slTemp.Count - 1 do
begin { Debug }
if debugMsg then
addMessage('[ItemKeyword] Result := ' + slTemp[i]);
result := slTemp[i]; { Debug }
if debugMsg then
addMessage('[ItemKeyword] EditorID(KWDAkeyword) := ' + EditorID(KWDAkeyword) + ') = Result := ' + slTemp[i] + ') then Exit;');
if (EditorID(KWDAkeyword) = result) then
begin
slTemp.Free;
exit;
end;
end;
result := nil;
end;
{ Debug } if debugMsg then
addMessage('[ItemKeyword] Result := nil; Exit;');
// Finalize
slTemp.Free;
debugMsg := false;
// End debugMsg section
end;
// Returns the BOD2 slot associated with the keyword
function KeywordToBOD2(aKeyword: string): string;
var
slTemp : TStringList;
debugMsg: boolean;
i : integer;
begin
// Begin debugMsg Section
debugMsg := false;
// Initialize
slTemp := TStringList.Create;
// Function
{ Debug } if debugMsg then
addMessage('[KeywordToBOD2] KeywordToBOD2(' + aKeyword + ' );');
slTemp.CommaText := 'ArmorHelmet, ClothingHead';
if slContains(slTemp, aKeyword) then
result := '30';
slTemp.CommaText := 'ArmorCuirass, ClothingBody';
if slContains(slTemp, aKeyword) then
result := '32';
slTemp.CommaText := 'ArmorGauntlets, ClothingHands';
if slContains(slTemp, aKeyword) then
result := '33';
slTemp.CommaText := 'ArmorBoots, ClothingFeet';
if slContains(slTemp, aKeyword) then
result := '37';
slTemp.CommaText := 'ArmorShield';
if slContains(slTemp, aKeyword) then
result := '39';
slTemp.CommaText := 'ClothingCirclet';
if slContains(slTemp, aKeyword) then
result := '42';
slTemp.CommaText := 'ClothingRing';
if slContains(slTemp, aKeyword) then
result := '36';
slTemp.CommaText := 'ClothingNecklace';
if slContains(slTemp, aKeyword) then
result := '35';
{ Debug } if debugMsg then
addMessage('[KeywordToBOD2] Result := ' + result);
// Finalize
slTemp.Free;
debugMsg := false;
// End debugMsg Section
end;
// Checks to see if a string ends with an entered substring [mte functions]
function StrEndsWith(s1, s2: string): boolean;
var
i, n1, n2: integer;
begin
result := false;
n1 := Length(s1);
n2 := Length(s2);
if (n1 < n2) then
exit;
result := (Copy(s1, n1 - n2 + 1, n2) = s2);
end;
// Appends a string to the end of the input string if it's not already there (from mte functions)
function AppendIfMissing(s1, s2: string): string;
begin
result := s1;
if not StrEndsWith(s1, s2) then
result := s1 + s2;
end;
// This function will allow you to find the position of a substring in a string. If the iteration of the substring isn't found -1 is returned.
function ItPos(substr: string; str: string; it: integer): integer;
var
debugMsg: boolean;
i, found: integer;
begin
// Begin debugMsg Section
debugMsg := false;
{ Debug } if debugMsg then
addMessage('[ItPos] substr := ' + substr);
{ Debug } if debugMsg then
addMessage('[ItPos] str := ' + str);
{ Debug } if debugMsg then
addMessage('[ItPos] it := ' + IntToStr(it));
{ Debug } if debugMsg then
addMessage('[ItPos] Result := -1');
result := -1;
// addMessage('Called ItPos('+substr+', '+str+', '+IntToStr(it)+')');
if it = 0 then
exit;
found := 0;
for i := 1 to Length(str) do
begin
// addMessage(' Scanned substring: '+Copy(str, i, Length(substr)));
if (Copy(str, i, Length(substr)) = substr) then
Inc(found);
if found = it then
begin
result := i;
break;
end;
end;
debugMsg := false;
// End debugMsg Section
end;
// Gets a template from and enchanted record
function GetEnchTemplate(e: IInterface): IInterface;
var
debugMsg: boolean;
begin
if ElementExists(e, 'CNAM') then
begin
result := LinksTo(ElementBySignature(e, 'CNAM'));
exit;
end;
if ElementExists(e, 'TNAM') then
begin
result := LinksTo(ElementBySignature(e, 'TNAM'));
exit;
end;
end;
// Checks if a string contains integers and then returns those integers
function IntWithinStr(aString: string): integer;
var
debugMsg : boolean;
i, x, tempInteger: integer;
slTemp, slItem : TStringList;
tempString : string;
begin
// Begin debugMsg Section
debugMsg := false;
// Initialize
if not Assigned(slTemp) then
slTemp := TStringList.Create
else
slTemp.clear;
if not Assigned(slItem) then
slItem := TStringList.Create
else
slItem.clear;
// Function
slTemp.CommaText := '0, 1, 2, 3, 4, 5, 6, 7, 8, 9';
for i := 1 to Length(aString) do
begin
tempString := Copy(aString, i, 1);
// {Debug} if debugMsg then addMessage('[IntWithinStr] tempString := '+tempString);
for x := 0 to slTemp.Count - 1 do
begin
if (tempString = slTemp[x]) then
begin { Debug }
if debugMsg then
addMessage('[IntWithinStr] ' + tempString + ' = ' + slTemp[x]);
if (slItem.Count = 0) then
begin { Debug }
if debugMsg then
addMessage('[IntWithinStr] slItem.Count-1 = 0');
slItem.Add(tempString); { Debug }
if debugMsg then
addMessage('[IntWithinStr] slItem.Add(' + tempString + ' );');
tempInteger := i; { Debug }
if debugMsg then
addMessage('[IntWithinStr] tempInteger := ' + IntToStr(tempInteger));
end else begin { Debug }
if debugMsg then
addMessage('[IntWithinStr] slItem.Count-1 <> 0');
{ Debug } if debugMsg then
addMessage('[IntWithinStr] if not (' + IntToStr(i) + ' - ' + IntToStr(tempInteger) + ' > 1) then begin');
if not(i - tempInteger > 1) then
begin { Debug }
if debugMsg then
addMessage('[IntWithinStr] slItem.Add(' + tempString + ' );');
slItem.Add(tempString); { Debug }
if debugMsg then
addMessage('[IntWithinStr] if not ' + IntToStr(i) + ' - ' + IntToStr(tempInteger) + ' > 1) then begin');
tempInteger := i; { Debug }
if debugMsg then
addMessage('[IntWithinStr] tempInteger := ' + IntToStr(i));
end;
end;
end;
end;
end;
{ Debug } if debugMsg then
addMessage('[IntWithinStr] if not slItem.Count := ' + IntToStr(slItem.Count) + ' = 0 then begin');
tempString := nil;
if not(slItem.Count = 0) then
begin
for i := 0 to slItem.Count - 1 do
begin
{ Debug } if debugMsg then
addMessage('[IntWithinStr] tempString := ' + tempString + ' + ' + slItem[i]);
tempString := tempString + slItem[i];
end;
if (Length(tempString) > 0) then
result := StrToInt(tempString);
{ Debug } if debugMsg then
addMessage('[IntWithinStr] Result := ' + IntToStr(result));
end
else
result := -1;
// Finalize
slTemp.Free;
slItem.Free;
debugMsg := false;
// End debugMsg Section
end;
// Finds if StringList contains substring
function StrWithinSL(s: string; aList: TStringList): boolean;
var
debugMsg: boolean;
i : integer;
begin
// Begin debugMsg section
debugMsg := false;
{ Debug } if debugMsg then
addMessage('[StrWithinSL] s := ' + s);
result := false;
for i := 0 to aList.Count - 1 do
begin
if ContainsText(aList[i], s) then
begin
result := true;
break;
end;
end;
debugMsg := false;
// End debugMsg section
end;
// Finds if StringList contains substring
function ContainsTextSL(aList, bList: TStringList): boolean;
var
debugMsg: boolean;
i : integer;
begin
// Begin debugMsg section
debugMsg := false;
{ Debug } if debugMsg then
addMessage('[ContainsTextSL] s := ' + s);
result := false;
for i := 0 to aList.Count - 1 do
begin
if StrWithinSL(aList[i], bList) then
begin
result := true;
exit
end;
end;
debugMsg := false;
// End debugMsg section
end;
// Finds if StringList contains substring
function SLWithinStr(s: string; aList: TStringList): boolean;
var
debugMsg: boolean;
i : integer;
begin
// Begin debugMsg section
debugMsg := false;
{ Debug } if debugMsg then
addMessage('[SLWithinStr] s := ' + s);
result := false;
for i := 0 to aList.Count - 1 do
begin
if ContainsText(s, aList[i]) then
begin
result := true;
break;
end;
end;
debugMsg := false;
// End debugMsg section
end;
// Fills a TStringList with 'true' flag values; Boolean controls if list gets just numbers or the whole element name
procedure slGetFlagValues(e: IInterface; aList: TStringList; aBoolean: boolean);
var
tempString, BinaryList: string;
startTime, stopTime : TDateTime;
slTemp : TStringList;
debugMsg : boolean;
i : integer;
begin
// Initialize
debugMsg := false;
startTime := Time;
if not Assigned(slTemp) then
slTemp := TStringList.Create
else
slTemp.clear;
// Function
if (Signature(e) = 'ARMO') then
begin
{ Debug } if debugMsg then
msgList('[slGetFlagValues] slGetFlagValues(' + EditorID(e) + ', ', aList, ', ' + BoolToStr(aBoolean));
slTemp.CommaText := FlagValues(ElementByPath(ElementBySignature(e, GetElementType(e)), 'First Person Flags'));
{ Debug } if debugMsg then
msgList('[slGetFlagValues] FlagValues := ', slTemp, '');
BinaryList := GetEditValue(ElementByPath(ElementBySignature(e, GetElementType(e)), 'First Person Flags'));
{ Debug } if debugMsg then
addMessage('[slGetFlagValues] BinaryList := ' + BinaryList);
if aBoolean then
begin
for i := 1 to Length(BinaryList) do
begin
if (Copy(BinaryList, i, 1) = '1') then
begin
if (i + 2 <= slTemp.Count - 1) then
begin
tempString := slTemp[3 * (i - 1)] + ' ' + slTemp[3 * (i - 1) + 1] + ' ' + slTemp[3 * (i - 1) + 2];
if not slContains(aList, tempString) then
aList.Add(tempString);
end;
end;
end;
end else begin
for i := 1 to Length(BinaryList) do
begin
if (Copy(BinaryList, i, 1) = '1') then
begin
if not slContains(aList, slTemp[3 * (i - 1)]) then
begin
{ Debug } if debugMsg then
addMessage('[slGetFlagValues] aList.Add(' + slTemp[3 * (i - 1)] + ' );');
aList.Add(slTemp[3 * (i - 1)]);
end;
end;
end;
end;
end
else
if (Signature(e) = 'LVLI') then
begin
{ Debug } if debugMsg then
msgList('[slGetFlagValues] slGetFlagValues(' + EditorID(e) + ', ', aList, ', ' + BoolToStr(aBoolean));
sl1.CommaText := '"Calculate from all levels <= player''s level", "Calculate for each item in count", "Use All", "Special Loot"';
{ Debug } if debugMsg then
msgList('[slGetFlagValues] FlagValues := ', slTemp, '');
end else begin
aList.Add(Signature(e));
slTemp.Free;
exit;
end;
// Finalize
slTemp.Free;
stopTime := Time;
if ProcessTime then
addProcessTime('slGetFlagValues', TimeBtwn(startTime, stopTime));
debugMsg := false;
end;
// Set Flag Values based on input string list
procedure slSetFlagValues(e: IInterface; aList: TStringList; aPlugin: IInterface);
var
tempString, BinaryList: string;
slTemp, sl1 : TStringList;
tempRecord : IInterface;
debugMsg : boolean;
i : integer;
begin
// Begin debugMsg section
debugMsg := false;
// Initialize
if not Assigned(slTemp) then
slTemp := TStringList.Create
else
slTemp.clear;
if not Assigned(sl1) then
sl1 := TStringList.Create
else
sl1.clear;
// Function
{ Debug } if debugMsg then
msgList('[slSetFlagValues] slSetFlagValues(' + EditorID(e) + ', ', aList, ' )');
if (Signature(e) = 'ARMO') then
begin
slTemp.CommaText := FlagValues(ElementByPath(ElementBySignature(e, GetElementType(e)), 'First Person Flags'));
{ Debug } if debugMsg then
msgList('[slSetFlagValues] FlagValues := ', slTemp, '');
BinaryList := GetEditValue(ElementByPath(ElementBySignature(e, GetElementType(e)), 'First Person Flags'));
{ Debug } if debugMsg then
addMessage('[slSetFlagValues] BinaryList := ' + BinaryList);
for i := 0 to slTemp.Count - 1 do
begin
// {Debug} if debugMsg then addMessage('[slSetFlagValues] if ('+IntToStr(i+2)+' <= '+IntToStr(slTemp.Count-1)+' ) then begin');
if (3 * (i) + 2 <= slTemp.Count - 1) then
begin
tempString := slTemp[3 * (i)] + ' ' + slTemp[3 * (i) + 1] + ' ' + slTemp[3 * (i) + 2];
if not slContains(sl1, tempString) then
sl1.Add(tempString);
i := i + 3;
end;
end;
{ Debug } if debugMsg then
msgList('[slSetFlagValues] sl1 := ', sl1, '');
slTemp.clear;
tempString := nil;
for i := 0 to sl1.Count - 1 do
begin
if slContains(aList, sl1[i]) then
begin
tempString := tempString + '1';
end else begin
tempString := tempString + '0';
end;
end;
{ Debug } if debugMsg then
addMessage('[slSetFlagValues] New BinaryList := ' + tempString);
if ContainsText(tempString, '1') then
SetEditValue(ElementByPath(ElementBySignature(e, GetElementType(e)), 'First Person Flags'), Copy(tempString, 0, rPos(tempString, '1')));
end
else
if (Signature(e) = 'LVLI') then
begin
// Make a copy of the list
tempRecord := MainRecordByEditorID(GroupBySignature(aPlugin, 'LVLI'), EditorID(e));
if not Assigned(tempRecord) then
begin
tempRecord := wbCopyElementToFile(e, aPlugin, false, true);
end;
// Assemble and assign new binary list
sl1.CommaText := '"Calculate from all levels <= player''s level", "Calculate for each item in count", "Use All", "Special Loot"';
{ Debug } if debugMsg then
msgList('[slGetFlagValues] FlagValues := ', sl1, '');
{ Debug } if debugMsg then
msgList('[slSetFlagValues] sl1 := ', sl1, '');
slTemp.clear;
tempString := nil;
for i := 0 to sl1.Count - 1 do
begin
if slContains(aList, sl1[i]) then
begin
tempString := tempString + '1';
end else begin
tempString := tempString + '0';
end;
end;
{ Debug } if debugMsg then
addMessage('[slSetFlagValues] New BinaryList := ' + Copy(tempString, 0, rPos(tempString, '1')));
if ContainsText(tempString, '1') then
SetEditValue(ElementBySignature(tempRecord, 'LVLF'), Copy(tempString, 0, rPos(tempString, '1')));
end else begin
aList.Add(Signature(e));
slTemp.Free;
exit;
end;
// Finalize
slTemp.Free;
sl1.Free;
debugMsg := false;
// End debugMsg section
end;
// Copies string preceding [TRUE] or following [FALSE] as string
function StrPosCopy(inputString: string; findString: string; inputBoolean: boolean): string;
var
debugMsg: boolean;
begin
// Begin debugMsg Section
debugMsg := false;
{ Debug } if debugMsg then
addMessage('[StrPosCopy] if ContainsText(inputString := ' + inputString + ', findString := ' + findString + ') then begin');
if ContainsText(inputString, findString) then
begin
{ Debug } if debugMsg then
addMessage('[StrPosCopy] if not inputBoolean := ' + BoolToStr(inputBoolean) + ' then');
if not inputBoolean then
begin
result := Copy(inputString, (ItPos(findString, inputString, 1) + Length(findString)), (Length(inputString) - ItPos(findString, inputString, 1)));
{ Debug } if debugMsg then
addMessage('[StrPosCopy] Copy(inputString := ' + inputString + ', (ItPos(findString := ' + findString + ' inputString := ' + inputString + ', 1)+length(findString) := ' + IntToStr(Length(findString)) + ') := ' + IntToStr(ItPos(findString, inputString, 1)) + ', (length(inputString) := ' + IntToStr(Length(inputString)) + ' - ItPos(findstring, inputString, 1)) := ' + IntToStr(ItPos(findString, inputString, 1)) + ')');
{ Debug } if debugMsg then
addMessage('[StrPosCopy] Result := ' + Copy(inputString, (ItPos(findString, inputString, 1) + Length(findString)), (Length(inputString) - ItPos(findString, inputString, 1))));
end;
{ Debug } if debugMsg then
addMessage('[StrPosCopy] if inputBoolean := ' + BoolToStr(inputBoolean) + ' then');
if inputBoolean then
begin
result := Copy(inputString, 0, (ItPos(findString, inputString, 1) - 1));
{ Debug } if debugMsg then
addMessage('[StrPosCopy] Copy(inputString := ' + inputString + ', 0, (ItPos(findString, inputString, 1)-1 := ' + IntToStr(ItPos(findString, inputString, 1) - 1) + '));');
{ Debug } if debugMsg then
addMessage('[StrPosCopy] Result := ' + Copy(inputString, 0, (ItPos(findString, inputString, 1) - 1)));
end;
end
else
result := Trim(inputString);
debugMsg := false;
// End debugMsg Section
end;
// Copies from end instead of beginning
function StrPosCopyReverse(inputString: string; findString: string; inputBoolean: boolean): string;
begin
if ContainsText(inputString, findString) then
begin
RemoveFromEnd(inputString, ' ');
if (findString = ' ') then
if Flip(inputBoolean) then
result := RemoveFromEnd(ReverseString(Copy(ReverseString(inputString), 0, ItPos(findString, ReverseString(inputString), 2) - Length(findString))), ' ')
else
result := RemoveFromEnd(ReverseString(Copy(ReverseString(inputString), ItPos(findString, ReverseString(inputString), 2) - Length(findString)), (Length(ReverseString(inputString)) - ItPos(findString, inputString, 2))), ' ')
else
result := ReverseString(StrPosCopy(ReverseString(inputString), findString, Flip(inputBoolean)))
// addMessage('[StrPosCopyReverse]'+ReverseString(inputString));
// addMessage('[StrPosCopyReverse]'+StrPosCopy(ReverseString(inputString), ' ', Flip(inputBoolean)));
// addMessage('[StrPosCopyReverse]'+ReverseString(StrPosCopy(ReverseString(inputString), ' ', Flip(inputBoolean))));
end
else
result := inputString;
end;
function Full(e: IInterface): string;
begin
result := GetElementEditValues(e, 'FULL');
end;
// This is just a ghetto way of replacing all the items with a single leveled list; Returns the first element in the list
function RefreshList(aRecord: IInterface; aString: string): IInterface;
var
debugMsg: boolean;
begin
// Begin debugMsg Section
debugMsg := false;
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] Remove(ElementByPath(' + GetElementEditValues(aRecord, 'EditorID') + ', ''' + aString + '''));');
Remove(ElementByPath(aRecord, aString));
{ Debug } if debugMsg then
addMessage('[AddToOutfitAuto] Add(' + GetFileName(aRecord) + ', ''' + aString + ''', True);');
Add(aRecord, aString, true);
result := elementbyindex(ElementByPath(aRecord, aString), 0);
debugMsg := false;
// End debugMsg Section
end;
// Find a record by name (e.x. 'IronSword')
function RecordByName(aName: string; aGroupName: string; aFileName: string): IInterface;
var
slTemp : TStringList;
i, slTempCount: integer;
begin
// Initialize
if not Assigned(slTemp) then
slTemp := TStringList.Create
else
slTemp.clear;
// Function
if not(StrEndsWith(aFileName, '.esm') or StrEndsWith(aFileName, '.esl') or StrEndsWith(aFileName, '.exe')) then
AppendIfMissing(aFileName, '.esp');
if (aFileName = 'Skyrim.esm') then
begin
slTemp := TStringList.Create;
slTemp.CommaText := 'Skyrim.esm, Dawnguard.esm, HearthFires.esm, Dragonborn.esm';
end else begin
slTemp := TStringList.Create;
slTemp.Add(aFileName);
end;
for slTempCount := 0 to slTemp.Count - 1 do
begin
for i := 0 to Pred(ElementCount(GroupBySignature(FileByName(slTemp[slTempCount]), aGroupName))) do
begin
if ContainsText(EditorID(elementbyindex(GroupBySignature(FileByName(slTemp[slTempCount]), aGroupName), i)), 'Ench') or ContainsText(GetElementEditValues(elementbyindex(GroupBySignature(FileByName(slTemp[slTempCount]), aGroupName), i)), 'Of') then
begin
Continue;
end
else
if ContainsText(EditorID(elementbyindex(GroupBySignature(FileByName(slTemp[slTempCount]), aGroupName), i)), aName) then
begin
result := elementbyindex(GroupBySignature(FileByName(slTemp[slTempCount]), aGroupName), i);
exit;
end;
end;
end;
// Finalize
slTemp.Free;
end;
// Removes s1 from the end of s2, if found [mte functions]
function RemoveFromEnd(s1, s2: string): string;
begin
result := s1;
if StrEndsWith(s1, s2) then
result := Copy(s1, 1, Length(s1) - Length(s2));
end;
// This adds a name-value pair in a way that allows for duplicate values
function slAddValue(aName, aValue: string): string;
var
slTemp : TStringList;
debugMsg: boolean;
begin
// Initialize
if not Assigned(slTemp) then
slTemp := TStringList.Create
else
slTemp.clear;
// Function
slTemp.Values[aValue] := aName;
if (slTemp.Count > 0) then
result := slTemp[0];
// Finalize
slTemp.Free;
end;
// Reverses a string.
function ReverseString(var s: string): string;
var
i: integer;
begin
result := '';
for i := Length(s) downto 1 do
begin
result := result + Copy(s, i, 1);
end;
end;
// find the last position of a substring in a string [mte Functions]
function rPos(aString, substr: string): integer;
var
i: integer;
begin
result := -1;
if (Length(aString) - Length(substr) < 0) then
exit;
for i := Length(aString) - Length(substr) downto 1 do
begin
if (Copy(aString, i, Length(substr)) = substr) then
begin
result := i;
break;
end;
end;
end;
// Converts a boolean value into a string [mte Functions]
function BoolToStr(b: boolean): string;
begin
if b then
result := 'True'
else
result := 'False';
end;
// Converts string to boolean
function StrToBool(s: string): boolean;
begin
if ContainsText(s, 'True') then
result := true
else
result := false;
end;
// Searches for string within TStringList
function slContains(aList: TStringList; s: string): boolean;
var
debugMsg: boolean;
i : integer;
begin
// Begin debugMsg section
debugMsg := false;
result := false;
{ Debug } if debugMsg then
msgList('[slContains] if ', aList, ' contains ' + s);
if (aList.IndexOf(s) <> -1) then
result := true;
debugMsg := false;
// End debugMsg section
end;
// Creates a leveled list
function createLeveledList(aPlugin: IInterface; aName: string; LVLF: TStringList; LVLD: integer): IInterface;
var
startTime, stopTime: TDateTime;
aLevelList : IInterface;
debugMsg : boolean;
begin
// Initialize
debugMsg := false;
startTime := Time;
{ Debug } if debugMsg then
msgList('[createLeveledList] createLeveledList(' + GetFileName(aPlugin) + ', ' + aName + ', ', LVLF, ', ' + IntToStr(LVLD) + ' );');
aLevelList := createRecord(aPlugin, 'LVLI');
SetElementEditValues(aLevelList, 'EDID', aName);
slSetFlagValues(aLevelList, LVLF, aPlugin);
if not(LVLD = 0) then
SetElementEditValues(aLevelList, 'LVLD', LVLD);
Add(aLevelList, 'Leveled List Entries', true);
RemoveInvalidEntries(aLevelList);
result := aLevelList;
{ Debug } if debugMsg then
addMessage('[createLeveledList] Result := ' + EditorID(result));
// Finalize
stopTime := Time;
if ProcessTime then
addProcessTime('createLeveledList', TimeBtwn(startTime, stopTime));
end;
// Converts Hex FormID to String
function HexToStr(aFormID: string): string;
begin
result := IntToStr(StrToInt(aFormID));
end;
function Flip(inputBoolean: boolean): boolean;
begin
if inputBoolean then
result := false
else
result := true;
end;
// gets record by IntToStr HEX FormID [SkyrimUtils]
function getRecordByFormID(id: string): IInterface;
var
startTime, stopTime: TDateTime;
tmp : IInterface;
begin
// Initialize
startTime := Time;
// basically we took record like 00049BB7, and by slicing 2 first symbols, we get IntToStr file index, in this case Skyrim (00)
tmp := FileByLoadOrder(StrToInt('$' + Copy(id, 1, 2)));
// file was found
if Assigned(tmp) then
begin
// look for this record in founded file, and return it
tmp := RecordByFormID(tmp, StrToInt('$' + id), true);
// check that record was found
if Assigned(tmp) then
begin
result := tmp;
end else begin // return nil if not
result := nil;
end;
end else begin // return nil if not
result := nil;
end;
// Finalize
stopTime := Time;
if ProcessTime then
addProcessTime('getRecordByFormID', TimeBtwn(startTime, stopTime));
end;
// Checks for keyword [SkyrimUtils]
function HasKeyword(aRecord: IInterface; aString: string): boolean;
var
tempRecord: IInterface;
debugMsg : boolean;
i : integer;
begin
// Begin debugMsg section
debugMsg := false;
result := false;
tempRecord := ElementByPath(aRecord, 'KWDA');
for i := 0 to Pred(ElementCount(tempRecord)) do
begin
{ Debug } if debugMsg then
addMessage('[HasKeyword] if (' + EditorID(LinksTo(elementbyindex(tempRecord, i))) + ' = ' + aString + ' ) then begin');
if (EditorID(LinksTo(elementbyindex(tempRecord, i))) = aString) then
begin
{ Debug } if debugMsg then
addMessage('[HasKeyword] Result := True');
result := true;
break;
end;
end;
debugMsg := false;
// End debugMsg section
end;
// Gets a keyword list [SkyrimUtils]
procedure slKeywordList(aRecord: IInterface; out aList: TStringList);
var
tempRecord: IInterface;
debugMsg : boolean;
i : integer;
begin
// Begin debugMsg section
debugMsg := false;
if debugMsg then
addMessage('slKeywordList start');
tempRecord := ElementByPath(aRecord, 'KWDA');
if not Assigned(aList) then
aList := TStringList.Create;
for i := 0 to ElementCount(tempRecord) - 1 do
aList.Add(EditorID(LinksTo(elementbyindex(tempRecord, i))));
if debugMsg then
addMessage('slKeywordList complete');
debugMsg := false;
// End debugMsg section
end;
// Adds keyword [SkyrimUtils]
function AddKeyword(itemRecord: IInterface; keyword: IInterface): integer;
var
keywordRef: IInterface;
begin
// don't edit records, which already have this keyword
if not HasKeyword(itemRecord, EditorID(keyword)) then
begin
// get all keyword entries of provided record
keywordRef := ElementByName(itemRecord, 'KWDA');
// record doesn't have any keywords
if not Assigned(keywordRef) then
begin
Add(itemRecord, 'KWDA', true);
end;
// add new record in keywords list
keywordRef := ElementAssign(ElementByPath(itemRecord, 'KWDA'), HighInteger, nil, false);
// set provided keyword to the new entry
SetEditValue(keywordRef, GetEditValue(keyword));
end;
end;
procedure AppendDelimited(out aStringList: TStringList; aSourceText: string);
var
sl: TStringList;
begin
sl := TStringList.Create;
sl.commatext := aSourceText;
aStringList.AddStrings(sl);
sl.Free;
end;
procedure Compact(out aStringList: TStringList);
var
slValueTiers: TStringList;
slCIL2 : TStringList;
slCIL : TStringList;
slValues : TStringList;
slEmpty : TStringList;
slPath2Temp : TStringList;
slPaths : TStringList;
sCIP : string;
sCIN : string;
sCIS : string;
sTemp: string;
iCT : integer;
iCIT: integer;
iMax: integer;
i : integer;
j : integer;
k : integer;
bDebug: boolean;
kCI: IInterface;
begin
bDebug := false;
slPaths := TStringList.Create;
// primary path
sTemp := aStringList.Objects[aStringList.IndexOf('sPath1')];
slPaths.addObject(Copy(sTemp, 0, Pos(':', sTemp) - 1), Copy(sTemp, Pos(':', sTemp), Length(sTemp) - 1));
// secondary slPaths
slPath2Temp := TStringList.Create;
slPath2Temp := aStringList.Objects[4];
for i := Pred(slPath2Temp.Count) downto 0 do
begin
sTemp := slPath2Temp.Objects[i];
slPaths.addObject(Copy(sTemp, 0, Pos(':', sTemp) - 1), Copy(sTemp, Pos(':', sTemp) + 1, Length(sTemp)));
end;
slValues := TStringList.Create;
iMax := aStringList.Objects[5];
for i := Pred(slPaths.Count) downto 0 do
begin
// initialize the slValues to have a proper name
slEmpty := TStringList.Create;
for i := 0 to Pred(slValues.Count) do
slEmpty.addObject(IntToStr(i), 0);
slValues.addObject(slPaths[i], slEmpty);
end;
i := 5;
repeat
if bDebug then
addMessage('generating compacted comparison slValues');
// get the value of sPath1 and slPath2 for each, and average them.
slCIL := TStringList.Create;
slCIL := aStringList.Objects[i]; // current r list
slCIL2 := TStringList.Create;
// process all items
for j := 0 to Pred(Length(slCIL)) do
begin
sCIS := IntToStr(slCIL.Objects[j]);
sCIP := Copy(sCIS, 0, Pos('|', sCIS) - 1);
sCIN := Copy(sCIS, Pos('|', sCIS) + 1, Pos(':', sCIS) - 1);
iCIT := StrToInt64Def(Copy(sCIS, Pos(':', sCIS) + 1, Length(sCIS)), 15);
kCI := RecordByEditorID(FileByName(sCIP), sCIN);
slCIL2.Add(iCIT);
slCIL2.Objects[j] := kCI;
end;
slCIL := slCIL2;
slCIL2.Free;
aStringList.addObject(aStringList[i] + 'slValues', slValues);
i := i + 2;
until i > aStringList.Count - 2;
i := 5;
repeat
if bDebug then
addMessage('generating compacted comparison slValues');
// get the value of sPath1 and slPath2 for each, and average them.
slCIL := aStringList.Objects[i]; // current r list
for j := Pred(Length(slCIL)) downto 0 do
begin // process all items
kCI := ObjectToElement(slCIL.Objects[j]);
iCT := StrToInt(slCIL[j]);
// process all items over all slPaths
for k := Pred(slPaths.Count) downto 0 do
begin
slValueTiers := slValues.Objects[k];
if iCT > iMax then
begin
addMessage('an r breached iMax level of selected template list');
Continue;
end;
// the extra math is for smoothing the curve a bit. probably could drop it easily.
slValueTiers.Objects[iCT] := slValueTiers.Objects[iCT] + (StrToFloatDef(GetElementEditValues(kCI, slPaths[k]), 1) * slPaths.Objects[k]);
end;
end;
aStringList.addObject(aStringList[i] + 'slValues', slValues);
i := i + 2;
until i > aStringList.Count - 2;
end;
function toUsable(aList: TStringList; grup: string): TStringList;
var
plugin,tr: IInterface;
edid,ts:string;
bList:TStringList;
i:integer;
begin
bList := TStringList.Create;
for i := 0 to pred(aList.Count) do begin
ts := aList[i];
//addMessage(ts);
plugin := FileByName(copy(ts, 0, pos('|', ts) - 1));
edid := copy(ts, pos('|', ts) + 1, length(ts));
tR := MainRecordByEditorID(GroupBySignature(plugin, grup), edid);
bList.addObject(edid, tr);
//addmessage(editorID(tr));
end;
result := bList;
end;
function badCheck(A: IInterface, sig: string): boolean; //return true when record meets common improper conditions
var
tempString:string;
begin
if not signature(a) = sig then begin
result := true;
exit;
end;
if signature(a) = 'LVLI' then begin
tempString := EditorID(a);
if ContainsText(tempString, '++')
or (Length(tempString) <= 0)
or FlagCheck(a, 'Special Loot') then
result := true;
end;
end;
function templatelistfilter2(grup, filter1, filter2, itemset: string): TStringList;
var
templist:TStringList;
begin
tempList := TStringList.Create;
{addmessage(itemset);
addmessage(filter1);
addmessage(filter2);}
tempList := IniStringlist(itemset + ' - ' + filter1, filter2, '');
templist.AddObject('comparison', comparisonGather(itemset + ' - ' + filter1));
//msgListObject('templist notgendered ', templist, ' hope it works?');
result := toUsable(templist, grup);
end;
function templatelistfilter2Gendered(grup, filter1, filter2, itemset: string;genders:TStringList): TStringList;
var
tempLista:TStringList;
templist:TStringList;
i:integer;
g:string;
begin
tempLista := TStringList.Create;
templist := TStringList.Create;
templist.AddObject('comparison', comparisonGather(itemset + ' - ' + filter1));
for i := 0 to pred(genders.count) do begin
g := genders[i];
tempList := IniStringlist(itemset + ' - ' + filter1 + ' - ' + g, filter2, '');
templista.addObject(g, toUsable(templist, grup));
templist.AddObject('comparison' + g, comparisonGather(itemset + ' - ' + filter1 + ' - ' + g));
end;
tempList := IniStringlist(itemset + ' - ' + filter1, filter2, '');
//msgListObject('templist gendered', templist, 'hope it works?');
templista.addobject('genderless', toUsable(templist, grup));
result := templista;
end;
function templateFilter1(grup, filter1, itemset: string; filter2: TStringList): TStringList;
var
templist:TStringList;
genders:TStringList;
gender:boolean;
i:integer;
begin
tempList := TStringList.Create;
gender := ini.readBool(itemset, 'gendered', false);
if not gender then begin
for i := 0 to pred(filter2.count) do begin
//msgListObject('templateFilter1g', templist, 'hope it works?');
templist.AddObject(filter2[i], templatelistfilter2(grup, filter1, filter2[i], itemset));
end;
end else begin
genders := IniStringList(itemset, 'genderIndicator', '');
for i := 0 to pred(filter2.count) do begin
//msgListObject('templateFilter1ng', templist, 'hope it works?');
templist.AddObject(filter2[i], templatelistfilter2Gendered(grup, filter1, filter2[i], itemset,genders));
end;
end;
result := tempList;
end;
function templateFilter0(grup, itemset: string; filter1, filter2: TStringList): TStringList;
var
templist:TStringList;
i:integer;
begin
tempList := TStringList.create;
for i := 0 to pred(filter1.count) do begin
//msgListObject('templateFilter0', templist, 'hope it works?');
tempList.AddObject(filter1[i], templateFilter1(grup, filter1[i], itemset, filter2));
end;
result := tempList;
end;
function ComparisonGather(itemset: string): TStringList;
var
cValue,cdescription,cdescriptor:TStringList;
templist,tempList2:TStringList;
ts,path,desType:string;
cl,cm:string;
i:integer;
begin
cValue := TStringList.Create;
cDescriptor := TStringList.Create;
cDescription := TStringList.Create;
//cvalue is easy. just p1 and the value.
cvalue.AddObject('p1',IniFloatLast(itemset,'comparison1',1));
cvalue.AddObject('p2',IniFloatLast(itemset,'comparison2',0.875));
cvalue.AddObject('p3',IniFloatLast(itemset,'comparison3',0.75));
cvalue.AddObject('p4',IniFloatLast(itemset,'comparison4',0.625));
cvalue.AddObject('p5',IniFloatLast(itemset,'comparison5',0.5));
cvalue.AddObject('p6',IniFloatLast(itemset,'comparison6',0.375));
//cdescriptor is a little harder, type and path needed.
for i := 0 to 5 do begin
cl := 'p' + intToStr(i+1);
tempList := TStringList.Create;
ts := IniStringLast(itemset, 'descriptor' + IntToStr(i+1), '');
path := copy(ts, 0, pos('|', ts) - 1);
desType := copy(ts, pos('|', ts) + 1, length(ts) - 1);
tempList.AddObject('path', path);
tempList.AddObject('type', desType);
cDescriptor.addobject(cl, tempList);
tempList.free;
end;
//cdescription is annoying. gotta include each item based on the type of cDescriptor.
for i := 0 to 5 do begin
cl := 'p' + intToStr(i+1);
cm := 'descriptions1' + IntToStr(i+1);
tempList2 := TStringList.Create;
tempList := getObject(cl,cvalue);
desType := getObject('type', tempList);
if desType = 's' then begin
//s is substrings within a string
templist2 := IniStringlist(itemset, cm, '');
end else if desType = 'b' then begin
//b is substrings within a string - but only whole terms (spaces separate)
templist2 := IniStringlist(itemset, cm, '');
end else if desType = 'f' then begin
//this is a specific formid
end else if desType = 'n' then begin
//this is a number. always assume float
//this is unnecessary.
end else if desType = 'e' then begin
//this is a group of subelements
templist2 := IniStringlist(itemset, cm, '');
{for i := 0 to pred(templist2.count) do begin
//should I implement this as assuming kywd? or should I assume nothing? should I keep this as just edids?
end;}
end;
cDescription.AddObject(cl,templist2);
tempList2.free;
end;
tempList := TStringList.Create;
tempList.addObject('values', cValue);
tempList.AddObject('descriptor', cDescriptor);
tempList.AddObject('descriptions', cDescription);
result := tempList;
end;
function templateitemsets(itemset: TStringList): TStringList;
var
i:integer;
ci, grup: string;
outList,templist,filter1,filter2: TStringList;
begin
outList := TStringList.Create;
for i := 0 to pred(itemset.count) do begin
ci := itemset[i];
addMessage('adding itemset group ' + ci + ' to template data');
filter1 := IniStringList(ci, 'result1', '');
//msgListObject('tis',filter1,'tis filter 1');
filter2 := IniStringList(ci, 'result2', '');
//msgListObject('tis',filter2,'tis filter 2');
grup := IniStringFirst(ci, 'type', '');
//addMessage(grup);
templist := TStringList.Create;
tempList.AddObject('grup', grup);
tempList.AddObject('splitList', splitf(ci, filter1, filter2));
tempList.AddObject('template', templateFilter0(grup, ci, filter1, filter2));
outList.addObject(ci, tempList);
end;
result := outList;
end;
function TemplateEnchants(modifiers: TStringList): TStringList;
begin
if (wbAppName = 'TES5') OR (wbAppName = 'SSE') then begin
//due to changes, all but ench will work for fo4. just need to implement it properly
end else if wbAppName = 'FO4' then begin
//this probably wont ever be implemented, but gonna leave it here just in case? for scopes and such or whatever?
end;
//TODO. need to determine a lot of stuff for this to work right.
end;
procedure TemplateMegaList;
var
itemset:TStringList;
begin
Megalist := TStringList.Create;
itemset := IniStringlist('values', 'itemsets', '');
//msgListObject('ml',itemset,'ml');
//modifiers := IniStringlist('values', 'modifiers', '');
Megalist.AddObject('items', templateitemsets(itemset));
Megalist.AddObject('enchants', TemplateEnchants(modifiers));
end;
procedure BOD2Setup;
var
i:integer;
begin
BOD2List := TStringList.Create;
for i := 30 to 60 do begin
BOD2List.AddObject(IntToStr(i),IniStringAll('bod2', i, ''));
end;
end;
function splitf(itemset: string; filter1, filter2: TStringList): TStringList;
var
split1,split2,genderfil:string;
templist,genderind:TStringList;
gendered:boolean;
begin
split1 := IniStringLast(itemset, 'split', '');
split2 := IniStringLast(itemset, 'split2', '');
gendered := StrToBool(IniStringLast(itemset, 'gendered', false));
tempList := TStringList.Create;
if gendered then begin
templist.addobject('gender', gendered);
genderfil := IniStringLast(itemset, 'genderFilter', false);
templist.addobject('genderFilter', genderfil);
genderind := IniStringlist(itemset, 'genderIndicator', false);
templist.addobject('genderIndicator', genderind);
end;
tempList.Addobject('split1', split1);
tempList.AddObject('split2', split2);
tempList.AddObject('result1', filter1);
tempList.AddObject('result2', filter2);
result := tempList;
end;
function IniStringLast(group, key, default: String): String;
var
i:integer;
memIniFile:TMemIniFile;
begin
for i := 0 to Pred(IniFileStreams.Count) do
begin
memIniFile := IniFileStreams.Objects[i];
default := memIniFile.ReadString(group, key, default);
end;
result := default;
end;
function IniStringFirst(group, key, default: String): String;
var
i:integer;
memIniFile:TMemIniFile;
begin
for i := Pred(IniFileStreams.Count) downto 0 do
begin
memIniFile := IniFileStreams.Objects[i];
default := memIniFile.ReadString(group, key, default);
end;
result := default;
end;
function IniStringAll(group, key, default: String): TStringList;
var
i:integer;
memIniFile:TMemIniFile;
temp:string;
tempList:TStringList;
begin
templist := TStringList.Create;
templist.Sorted := True;
templist.Duplicates := dupIgnore;
for i := Pred(IniFileStreams.Count) downto 0 do
begin
memIniFile := IniFileStreams.Objects[i];
temp := memIniFile.ReadString(group, key, '');
if pos(temp, ',') < 0 then
AppendDelimited(tempList, temp);
end;
if tempList.Count < 1 then templist.add(default);
result := tempList;
end;
function IniStringlist(group, key, default: String): TStringList;
var
i:integer;
memIniFile:TMemIniFile;
templist:TStringList;
begin
templist := TStringList.Create;
templist.Sorted := True;
templist.Duplicates := dupIgnore;
for i := Pred(IniFileStreams.Count) downto 0 do
begin
memIniFile := IniFileStreams.Objects[i];
//addmessage(memIniFile.ReadString(group, key, ''));
AppendDelimited(templist, memIniFile.ReadString(group, key, ''));
end;
if tempList.Count < 1 then templist.add(default);
result := templist;
end;
function IniFloatFirst(group, key: String; default: double): double;
var
i:integer;
memIniFile:TMemIniFile;
default:double;
begin
for i := Pred(IniFileStreams.Count) downto 0 do
begin
memIniFile := IniFileStreams.Objects[i];
default := memIniFile.ReadFloat(group, key, default);
end;
result := default;
end;
function IniFloatLast(group, key: String; default: double): double;
var
i:integer;
memIniFile:TMemIniFile;
default:double;
begin
for i := 0 to Pred(IniFileStreams.Count) do
begin
memIniFile := IniFileStreams.Objects[i];
default := memIniFile.ReadFloat(group, key, default);
end;
result := default;
end;
procedure template;
var
IniTemplates,memIniFile: TMemIniFile;
i: integer;
itemset:tStringList;
begin
IniFileStreams := TStringList.Create;
// setup template files
// ALLATemplate.ini
// ALLAUserTemplate.ini
// ALLA+<modname>+template.ini in data folder (ie: ALLAYggKeywords.espTemplate.ini)
IniTemplates := TStringList.Create;
IniTemplates.Add(ScriptsPath + 'ALLATemplate.ini');
IniTemplates.Add(ScriptsPath + 'ALLAUserTemplate.ini');
for i := 0 to Pred(FileCount) do
if FileExists(DataPath + 'alla' + GetFileName(FileByIndex(i)) + 'template.ini') then
IniTemplates.Add(DataPath + 'alla' + GetFileName(FileByIndex(i)) + 'template.ini');
addMessage('[TemplateLists] detected ' + IntToStr(IniTemplates.Count) + ' Template Inis');
for i := Pred(IniTemplates.Count) downto 0 do
begin
memIniFile := TMemIniFile.Create(IniTemplates[i]);
IniFileStreams.addObject(IniTemplates[i], memIniFile);
end;
for i := Pred(IniTemplates.Count) downto 0 do
begin
memIniFile := TMemIniFile.Create(IniTemplates[i]);
IniFileStreams.addObject(IniTemplates[i], memIniFile);
end;
memIniFile := TMemIniFile.Create(IniTemplates[1]);
if not Assigned(memIniFile) then
addMessage('stupid');
IniFileStreams.addObject(IniTemplates[1], memIniFile);
itemset := IniStringList('values','items','armor,weapons,ammo');
templateMegalist;
BOD2Setup;
end;
function GetTemplate(aRecord: IInterface): IInterface;
var
CIS,CL: TStringList;
grup:string;
split,result1,result2:TStringList;
split1,split2: string;
g:boolean;
gf:string;
gI:TStringList;
i:integer;
cr:IInterface;
cre:string;
gender:string;
p1:IInterface;
cK:IInterface;
j:integer;
r1:string;
p2: IInterface;
r2:string;
listr1,listr2,glist,comparison:TStringList;
sig: string;
begin
addmessage('gettemplate');
sig := LowerCase(signature(aRecord));
CL := megalist.objects[megalist.indexOf('items')]; //get itemsets (list) from megalist
for i := 0 to pred(CL.count) do begin
CIS := CL.objects[i]; //get itemset (list) from itemsets
grup := LowerCase(CIS.objects[CIS.indexOf('grup')]); //get grup (string) from itemset
addmessage(grup);
addmessage(sig);
if sig = grup then break;
end;
if not pos(sig, grup) > -1 then begin
result := Nil;
addmessage('no matching signature for ' + editorID(aRecord));
exit;
end;
split := CIS.objects[CIS.indexOf('splitList')]; //get split (list) from itemset
//msgListObject('split ', split, '');
split1 := split.objects[split.indexOf('split1')]; //get split1 (string) from split
split2 := split.objects[split.indexOf('split2')]; //get split2 (string) from split
result1 := split.objects[split.indexOf('result1')]; //get result1 (list) from split
result2 := split.objects[split.indexOf('result2')]; //get result2 (list) from split
if slContains(split, 'gender') then
g := split.objects[split.indexof('gender')]; //get gender (string) from split
if g then begin
gF := split.objects[split.indexof('genderFilter')]; //if gendered, get filter (string) from split
gI := split.objects[split.indexof('genderIndicator')]; //if gendered, get indicator(s) (list) from split
if (length(gF) = 0) or (length(gI) = 0) then begin
result := Nil;
exit;
end;
if StrEndsWith(gF, '/') then begin
cP := ElementByPath(aRecord, gF);
for i := 0 to pred(elementCount(cP)) do begin
cK := ElementByIndex(cP, i);
if length(GetEditValue(cK)) < 1 then begin //test to see if nested subrecord in element. probably a cleaner way to do it. hopefully someone sends it to me…
cR := ElementByIndex(cK, 0);
cRE := GetEditValue(cR);
if slContains(gI, cRE) then begin
for i := 0 to gI.count - 1 do begin
if gI[i] = cRE then begin
gender := gI[i];
break;
end;
end;
end;
end else begin
cR := cK;
if slContains(gI, GetEditValue(cR)) then begin
for i := 0 to gI.count - 1 do begin
if gI[i] = cRE then begin
gender := gI[i];
break;
end;
end;
end;
end;
end;
end;
end;
p1 := ElementByPath(aRecord, split1);
if StrEndsWith(split1, '/') then begin
for i := 0 to elementCount(p1) - 1 do begin
cK := ElementByIndex(p1, i);
if length(GetEditValue(cK)) < 1 then begin //test to see if nested subrecord in element. probably a cleaner way to do it. hopefully someone sends it to me…
for j := 0 to result1.count - 1 do begin
if GetEditValue(p1) = result1[j] then begin
r1 := result1[j];
break;
end;
end;
end else begin
for j := 0 to result1.count - 1 do begin
if GetEditValue(p1) = result1[j] then begin
r1 := result1[j];
break;
end;
end;
end;
end;
end else begin
for i := 0 to result1.count - 1 do begin
if GetEditValue(p1) = result1[i] then begin
r1 := result1[i];
break;
end;
end;
end;
p2 := ElementByPath(aRecord, split2);
if StrEndsWith(split2, '/') then begin
for i := 0 to elementCount(p2) - 1 do begin
cK := ElementByIndex(p2, i);
if length(GetEditValue(cK)) < 1 then begin //test to see if nested subrecord in element. probably a cleaner way to do it. hopefully someone sends it to me…
for j := 0 to result2.count - 1 do begin
if GetEditValue(p2) = result2[j] then begin
r2 := result2[j];
break;
end;
end;
end else begin
for j := 0 to result2.count - 1 do begin
if GetEditValue(p2) = result2[j] then begin
r2 := result2[j];
break;
end;
end;
end;
end;
end else begin
for i := 0 to result1.count - 1 do begin
if GetEditValue(p2) = result2[i] then begin
r2 := result2[i];
break;
end;
end;
end;
//r1, r2
if slContains(CIS, r1) then
listr1 := CIS.objects[CIS.IndexOf(r1)]
else begin
result := aRecord;
exit;
end;
if slContains(listr1, r2) then
listr2 := listr1.objects[listr1.indexOf(r2)]
else begin
result := aRecord;
exit;
end;
if not assigned(listr2) then begin
result := Nil;
exit;
end;
if g and assigned(gender) then begin
if slContains(listr2, gender) then
glist := listr2.objects[listr2.indexof(gender)];
comparison := listr2.objects[listr2.indexOf('comparison' + g)];
end else if g then begin
if slContains(listr2, 'genderless') then
glist := listr2.objects[listr2.indexof('genderless')];
comparison := listr2.objects[listr2.indexOf('comparison')];
end else begin
gList := listr2.objects[0];
comparison := listr2.objects[listr2.indexOf('comparison')];
end;
if not assigned(glist) then begin
result := Nil;
exit;
end;
result := compare(aRecord, glist, comparison);
addmessage('original: ' editorID(aRecord) + 'template: ' + EditorID(result));
end;
function compare(aRecord: IInterface; list,comps: tStringList): IInterface;
begin
comparisonCount := 6;
Value := comps.objects[comps.indexOf('values')];
Descriptor := comps.objects[comps.indexOf('descriptor')];
Description := comps.objects[comps.indexOf('descriptions')];
for i := pred(list) to 0 do begin
current := ObjectToElement(list.objects[i]);
for j := 1 to comps do begin
cs := 'p' + intToStr(j);
cv := value.objects[value.indexOf(cs)];
cdr := Descriptor.objects[Descriptor.indexOf(cs)];
cdt := copy(cdr, cdr.length - 3, 2);
cdr := delete(2, cdr);
cdn := Description.objects[Description.indexOf(cs)];
if cdt = '|n' then begin
currentComp := StrToFloatDef(getelementeditvalue(current, cdr), 0);
itemComp := StrToFloatDef(getelementeditvalue(aRecord, cdr),50);
tvalue := tvalue + numcomp(itemComp,currentcomp,cv);
end else if cdt = '|s' then begin
currentComp := getelementeditvalue(current, cdr);
itemComp := getelementeditvalue(aRecord, cdr);
tValue := tvalue + strComp(itemComp,currentComp,cdr,cv);
end else if cdt = '|b' then begin
currentComp := ElementByName(current, cdr);
itemComp := ElementByName(aRecord, cdr);
tValue := tvalue + strComp(itemComp,currentComp,cdr,cv);
end else if cdt = '|e' then begin
currentComp := ElementByName(current, cdr);
itemComp := ElementByName(aRecord, cdr);
tValue := tvalue + edidComp(itemComp,currentComp,cv);
end;
end;
if (j = 1) or (presentvalue > maxValue) then begin
maxValue := presentvalue;
bestItem := i;
end;
end;
result := list.objects[i];
end;
function NumComp(v1,v2,c: double):double;
begin
//v2 is from template
//c is comparison value
if v1 > v2 + 1 then begin
result := 5*abs((v2/v1)*(v1/(c-v1+((2*v2)(v2/v1)))))
end else if v2 > v1 + 1 then begin
result := 5*abs((v2/v1)*(v1/(c-v1-((2*v2)(v2/v1)))))
end else begin
result := c;
end;
end;
function strComp(v1,v2:string;des: tStringList;c: double):double;
begin
for i := 0 to pred(des.count) do begin
if ContainsText(v1,des[i]) and ContainsText(v2,des[i]) then begin
a := a + 1;
end;
end;
result := c * a;
end;
function substrComp(v1,v2:string;des: tStringList;c: double):double;
begin
for i := 0 to pred(des.count) do begin
for j := 0 to pred(elementCount(v1)) do begin
for k := 0 to pred(elementCount(v2)) do begin
if containsText(GetEditValue(ElementByIndex(v1,j)),des[i]) and ContainsText(GetEditValue(ElementByIndex(v2,j)), des[i]) then begin
a := a + 1;
end;
end;
end;
end;
result := a * c;
end;
function edidComp(v1,v2:string;c:double):double;
begin
for i := 0 to pred(ElementCount(v1)) do begin
for j := 0 to pred(ElementCount(v2)) do begin
if equals(v1,v2) then begin
a := a + 1;
end;
end;
end;
result := a*c;
end;
function YggCompareStrings(aString, bString: TStringList): integer;
var
a : integer;
b : integer;
i : integer;
j : integer;
tempi: integer;
aList: TStringList;
bList: TStringList;
begin
a := Length(aString);
b := Length(bString);
if a > 5 then
begin
for i := 0 to a - 1 do
begin
for j := a - 1 downto i + 4 do
begin
aList.Add(Copy(aString, i, j));
end;
end;
end
else
result := 0;
if b > 5 then
begin
for i := 0 to bString - 1 do
begin
for j := bString - 1 downto i + 4 do
begin
bList.Add(Copy(bString, i, j));
end;
end;
end
else
result := 0;
tempi := CompareStringLists(aList, bList);
if tempi / 10 > 1 then
result := floor(tempi / 10)
else
if tempi > 1 then
result := 1;
else
result := 0;
end;
function CompareStringLists(aStringList: TStringList; aOtherStringList: TStringList): integer;
var
i : integer;
iCount: integer;
iIndex: integer;
begin
aStringList.Sort;
aOtherStringList.Sort;
iCount := 0;
for i := 0 to Pred(aStringList.Count) do
begin
iIndex := aOtherStringList.IndexOf(aStringList[i]);
if not(iIndex < 0) then
begin
aStringList.Delete[iIndex];
iCount := iCount + 1;
end;
end;
result := iCount;
end;
function SameKeywordCount(aRecord: IInterface; aOtherRecord: IInterface): integer;
var
bDebug: boolean;
i : integer;
begin
// Begin debugMsg section
bDebug := false;
result := false;
kTempRecord := ElementBySignature(aRecord, 'KWDA');
for i := 0 to Pred(ElementCount(kTempRecord)) do
if HasKeyword(aOtherRecord, elementbyindex(kTempRecord, i)) then
total := total + 1;
bDebug := false;
// End debugMsg section
end;
function SubTemplateSelector(aRecord: IInterface; aTemplateList: TStringList): TStringList;
var
i : integer;
slSubTemplate: TStringList;
slPartType : TStringList;
sCTLN : string;
sCTLN1 : string;
begin
repeat
i := i + 1;
until i = aTemplateList.Count - 1 or ContainsText(aTemplateList[i], 'aKeywords');
while i < aTemplateList.Count - 2 do
begin
if not ContainsText(aTemplateList[i], aKeywords) then
break;
slPartType := aTemplateList.Objects[i];
sCTLN := aTemplateList[i];
sCTLN1 := aTemplateList[i - 1];
slSubTemplate := TStringList.Create;
if HasAKeyword(aRecord, slPartType) then
if ContainsText(sCTLN, sCTLN1) then
begin
slSubTemplate.AddObjects(sCTLN1, aTemplateList.Objects[i - 1]);
slSubTemplate.AddObjects(sCTLN1 + 'slValues', aTemplateList.Objects[aTemplateList.IndexOf(sCTLN1 + 'slValues')]);
result := slSubTemplate;
exit;
end;
i := i + 2;
end;
end;
function GetTier(aRecord: IInterface; aTemplateList: TStringList; aTemplateMain: TStringList): TStringList;
var
slPath2Temp : TStringList;
slPath2 : TStringList;
slValueSublist: TStringList;
slValue : TStringList;
sTemp : string;
sPath1 : string;
dPrimePathCR : Double;
dPath1Comp : Double;
dPath2T : Double;
dPath2A : Double;
i : integer;
j : integer;
iTier : integer;
begin
// Result here will be a list of items in the iTier
slValue := aTemplateList.Objects[1];
// primary path for comparison
sPath1 := Copy(aTemplateMain.Objects[3], 0, Pos(':', aTemplateMain.Objects[3]) - 1);
// sPath1 mult value
dPath1Comp := StrToFloatDef(Copy(sTemp, Pos(':', sTemp) + 1, sTemp.Length), 1);
slPath2Temp := aTemplateMain.Objects[4];
for i := Pred(slPath2Temp.Count) downto 0 do
begin
sTemp := slPath2Temp.Objects[i];
slPath2.addObject(Copy(sTemp, 0, Pos(':', sTemp) - 1), StrToFloatDef(Copy(sTemp, Pos(':', sTemp) + 1, sTemp.Length), 1));
end;
slValueSublist := slValue.Objects[slValue.IndexOf(sPath1)];
dPrimePathCR := StrToFloatDef(GetElementEditValues(aRecord, sPath1), 1) * dPath1Comp;
for i := 0 to Pred(slValueSublist.Count) do
begin
if dPrimePathCR > slValueSublist.Objects[i] + 1 then
Continue;
if dPrimePathCR < slValueSublist.Objects[i] - 1 then
begin
i := i - 1;
break;
end;
break;
end;
iTier := i;
addMessage('primary iTier for ' + DisplayName(aRecord) + ' is ' + iTier + ' processing secondary modifiers now');
for i := 0 to Pred(slPath2.Count) do
begin
slValueSublist := slValue.Objects[slValue.IndexOf(slPath2[i])];
for j := 0 to Pred(slValueSublist.Count) do
begin
if dPrimePathCR > slValueSublist.Objects[j] + 1 then
Continue;
if dPrimePathCR < slValueSublist.Objects[j] - 1 then
begin
j := j - 1;
break;
end;
break;
end;
dPath2T := dPath2T + j;
end;
dPath2A := dPath2T / slPath2.Count;
if iTier < dPath2A - 10 then
iTier := iTier - 3
else
if iTier < dPath2A - 7 then
iTier := iTier - 2
else
if iTier < dPath2A - 3 then
iTier := iTier - 1
else
if iTier > dPath2A + 10 then
iTier := iTier + 3
else
if iTier < dPath2A + 7 then
iTier := iTier + 2
else
if iTier < dPath2A + 3 then
iTier := iTier + 1;
addMessage('with alternative slPaths, iTier is now ' + iTier);
end;
function TemplateListSelector(aRecord: IInterface): TStringList;
var
slValues: TStringList;
i : integer;
begin
// 2 options, find first applicable template section based on aIdents
// find the most applicable. first easier.
for i := 0 to Pred(TemplateMegaListvar.Count) do
begin
slValues := TemplateMegaListvar.Objects[i];
if not StrWithinSL(Signature(aRecord), slValues.Objects[slValues.IndexOf('grup')]) then
Continue;
if not HasIdent(aRecord, slValues.Objects[slValues.IndexOf('identifier')]) then
Continue;
result := slValues;
exit;
end;
end;
function HasAKeyword(aRecord: IInterface; aKeywords: TStringList): boolean;
var
bDebug : boolean;
kTempRecord: IInterface;
i : integer;
j : integer;
begin
// Begin debugMsg section
bDebug := false;
result := false;
kTempRecord := ElementBySignature(aRecord, 'KWDA');
for i := 0 to Pred(ElementCount(kTempRecord)) do
begin
for j := 0 to Pred(aKeywords.Count) do
begin
if bDebug then
addMessage('[HasAKeyword] if (' + EditorID(LinksTo(elementbyindex(kTempRecord, i))) + ' = ' + aKeywords[j] + ' ) then begin');
if SameText(EditorID(LinksTo(elementbyindex(kTempRecord, i))), aKeywords[j]) then
begin
if bDebug then
addMessage('[HasAKeyword] Result := True');
result := true;
exit;
end;
end;
end;
bDebug := false;
// End debugMsg section
end;
function HasIdent(aRecord: IInterface; aIdents: TStringList): boolean;
var
sTempEDID: string;
sTempName: string;
i : integer;
begin
sTempEDID := EditorID(aRecord);
sTempName := DisplayName(aRecord);
result := false;
for i := Pred(aIdents.Count) downto 0 do
if ContainsText(sTempEDID, aIdents[i]) or ContainsText(sTempName, aIdents[i]) then
begin
result := true;
exit;
end;
end;
// gets templetes for books
// todo fix paths for SPIT\Half-cost Perk and SPIT/BASE COST
function BookTemplate(bookRecord: IInterface): IInterface;
var
books, flags, tempSpellRecord: IInterface;
halfCostPerk : string;
begin
if (GetEditValue(ElementByPath(selectedRecord, 'DATA\Flags\Teaches spell'))) = '1' then
begin // checks if book is tome
tempSpellRecord := LinksTo(ElementByPath(bookRecord, 'DATA\Flags\Teaches')); // spell from tome
if not(LinksTo(ElementByPath(tempSpellRecord, 'SPIT\Half-cost Perk')) = nil) then
begin
halfCostPerk := GetElementEditValues(tempSpellRecord, 'SPIT\Half-cost Perk');
{ Debug } addMessage('halfCostPerk' + halfCostPerk);
case extractInts(halfCostPerk, 1) of
00:
begin
case ElementByPath(halfCostPerk, 'Novice', true) of
'Alteration':
result := getRecordByFormID('0009E2A7');
'Conjuration':
result := getRecordByFormID('0009E2AA');
'Destruction':
result := getRecordByFormID('0009CD52');
'Illusion':
result := getRecordByFormID('0009E2AD');
'Restoration':
result := getRecordByFormID('0009E2AE');
end;
end;
25:
begin
case ElementByPath(halfCostPerk, 'Apprentice', true) of
'Alteration':
result := getRecordByFormID('000A26E3');
'Conjuration':
result := getRecordByFormID('0009CD54');
'Destruction':
result := getRecordByFormID('000A2702');
'Illusion':
result := getRecordByFormID('000A270F');
'Restoration':
result := getRecordByFormID('000A2720');
end;
end;
50:
begin
case ElementByPath(halfCostPerk, 'Adept', true) of
'Alteration':
result := getRecordByFormID('000A26E7');
'Conjuration':
result := getRecordByFormID('000A26EE');
'Destruction':
result := getRecordByFormID('000A2708');
'Illusion':
result := getRecordByFormID('000A2714');
'Restoration':
result := getRecordByFormID('0010F64D');
end;
end;
75:
begin
case ElementByPath(halfCostPerk, 'Expert', true) of
'Alteration':
result := getRecordByFormID('000A26E8');
'Conjuration':
result := getRecordByFormID('000A26F7');
'Destruction':
result := getRecordByFormID('0010F7F4');
'Illusion':
result := getRecordByFormID('000A2718');
'Restoration':
result := getRecordByFormID('000A2729');
end;
end;
100:
begin
case ElementByPath(halfCostPerk, 'Master', true) of
'Alteration':
result := getRecordByFormID('000DD646');
'Conjuration':
result := getRecordByFormID('000A26FA');
'Destruction':
result := getRecordByFormID('000A270D');
'Illusion':
result := getRecordByFormID('000A2719');
'Restoration':
result := getRecordByFormID('000FDE7B');
end;
end;
end;
end else begin // uses restoration books as level list base
case StrToInt(GetElementEditValues(tempSpellRecord, 'SPIT/BASE COST')) of
0 .. 96:
result := getRecordByFormID('0009E2AE'); // novice
97 .. 156:
result := getRecordByFormID('000A2720'); // aprentice
157 .. 250:
result := getRecordByFormID('0010F64D'); // adept
251 .. 644:
result := getRecordByFormID('000A2729'); // expert
else
result := getRecordByFormID('000FDE7B'); // master
end;
end;
end;
end;
// extracts the specified integer (Natural Numbers only) from an input; returns -1 if no suitable number is not found
// O(10n) time complexity n =input string length
function extractInts(inputString: string; intToPull: integer): integer; // tested and works
const
ints = '1234567890';
var
i, j, currentInt: integer;
flag1, flag2 : boolean;
resultString : string;
begin
resultString := '';
currentInt := 0;
flag1 := true;
flag2 := true;
for i := 0 to (Length(inputString) - 1) do
begin
j := 0;
while j < 10 do
begin
if Copy(inputString, i + 1, 1) = Copy(ints, j + 1, 1) then
begin
if flag1 then
currentInt := currentInt + 1;
if (currentInt = intToPull) then
resultString := resultString + Copy(inputString, i + 1, 1);
flag1 := false;
flag2 := false;
break;
end;
j := j + 1;
end;
if flag2 then
flag1 := true;
flag2 := true;
end;
if not(resultString = '') then
result := StrToInt(resultString)
else
result := -1
end;
// Gets a HexFormID
function HexFormID(e: IInterface): string;
begin
result := IntToHex(GetLoadOrderFormID(e), 8);
end;
// Adds requirement 'HasPerk' to Conditions list [SkyrimUtils]
function addPerkCondition(aList: IInterface; aPerk: IInterface): IInterface;
var
newCondition, tempRecord: IInterface;
debugMsg : boolean;
begin
// Begin debugMsg section
debugMsg := false;
if not(name(aList) = 'Conditions') then
begin
if Signature(aList) = 'COBJ' then
begin // record itself was provided
tempRecord := ElementByPath(aList, 'Conditions');
if not Assigned(tempRecord) then
begin
Add(aList, 'Conditions', true);
aList := ElementByPath(aList, 'Conditions');
newCondition := elementbyindex(aList, 0); // xEdit will create dummy condition if new list was added
end
else
aList := tempRecord;
end;
end;
if not Assigned(newCondition) then
newCondition := ElementAssign(aList, HighInteger, nil, false);
// set type to Equal to
SetElementEditValues(newCondition, 'CTDA - \Type', '10000000');
// set some needed properties
SetElementEditValues(ElementByPath(newCondition, 'CTDA'), 'Type', '10000000');
SetElementEditValues(ElementByPath(newCondition, 'CTDA'), 'Comparison Value', '1');
SetElementEditValues(ElementByPath(newCondition, 'CTDA'), 'Function', 'HasPerk');
SetElementEditValues(ElementByPath(newCondition, 'CTDA'), 'Perk', GetEditValue(aPerk));
SetElementEditValues(ElementByPath(newCondition, 'CTDA'), 'Run On', 'Subject');
SetElementEditValues(ElementByPath(newCondition, 'CTDA'), 'Parameter #3', '-1');
RemoveInvalidEntries(aList);
result := newCondition;
debugMsg := false;
// End debugMsg section
end;
// Gets the relevant game value
function GetGameValue(aRecord: IInterface): string;
var
slTemp : TStringList;
debugMsg: boolean;
i : integer;
begin
// Initialize
debugMsg := false;
slTemp := TStringList.Create;
{ Debug } if debugMsg then
addMessage('GetGameValue(' + EditorID(aRecord) + ' );');
// Function
slTemp.CommaText := 'Circlet, Ring, Necklace';
if (Signature(aRecord) = 'ARMO') then
begin
for i := 0 to slTemp.Count - 1 do
begin
if ContainsText(GetElementEditValues(aRecord), slTemp[i]) or ContainsText(ItemKeyword(aRecord), slTemp[i]) or HasKeyword(aRecord, ('Clothing' + slTemp[i])) then
begin
result := GetElementEditValues(aRecord, 'DATA\Value');
exit
end;
end;
result := StrPosCopy(GetElementEditValues(aRecord, 'DNAM'), '.', true);
exit;
end
else
if (Signature(aRecord) = 'AMMO') then
begin
result := StrPosCopy(GetElementEditValues(aRecord, 'DATA\Damage'), '.', true);
exit;
end else begin
result := GetElementEditValues(aRecord, 'DATA\Damage');
exit;
end;
// Finalize
slTemp.Free;
end;
// Gets the relevant game value type
function GetGameValueType(inputRecord: IInterface): string;
var
slTemp: TStringList;
i : integer;
begin
// Initialize
slTemp := TStringList.Create;
// Function
slTemp.CommaText := 'Circlet, Ring, Necklace';
if Signature(inputRecord) = 'ARMO' then
begin
for i := 0 to slTemp.Count - 1 do
begin
if ContainsText(GetElementEditValues(inputRecord, 'FULL'), slTemp[i]) or ContainsText(ItemKeyword(inputRecord), slTemp[i]) or (ItemKeyword(inputRecord) = ('Clothing' + slTemp[i])) then
begin
result := 'DATA\Value';
exit;
end;
end;
result := 'DNAM';
exit;
end else begin
result := 'DATA\Damage';
exit;
end;
// Finalize
slTemp.Free;
end;
// Removes spaces from a string
function RemoveSpaces(inputString: string): string;
var
debugMsg : boolean;
tempString: string;
begin
// Begin debugMsg Section
debugMsg := false; { Debug }
if debugMsg then
addMessage('[RemoveSpaces] Trim(inputString := ' + inputString + ')');
Trim(inputString); { Debug }
if debugMsg then
addMessage('[RemoveSpaces] tempString := inputString);');
while (rPos(inputString, ' ') > 0) do
begin
{ Debug } if debugMsg then
addMessage('[RemoveSpaces] while (rPos(inputString, ' ') := ' + IntToStr(rPos(inputString, ' ')) + ' > 0) do begin');
{ Debug } if debugMsg then
addMessage('[RemoveSpaces] inputString := ' + inputString);
{ Debug } if debugMsg then
addMessage('[RemoveSpaces] tempString := ' + tempString);
Delete(inputString, rPos(inputString, ' '), 1);
end;
{ Debug } if debugMsg then
addMessage('Result := ' + inputString);
result := inputString;
debugMsg := false;
// End debugMsg Section
end;
// Checks if a level list contains a record
function LLcontains(aLevelList, aRecord: IInterface): boolean;
var
debugMsg: boolean;
i : integer;
begin
// Begin debugMsg Section
debugMsg := false;
result := false;
{ Debug } if debugMsg then
addMessage('[LLcontains] LLcontains(' + EditorID(aLevelList) + ', ' + EditorID(aRecord) + ' );');
for i := 0 to Pred(LLec(aLevelList)) do
begin
{ Debug } if debugMsg then
addMessage('[LLcontains] LLelementbyindex := ' + EditorID(LLelementbyindex(aLevelList, i)));
// nb097 - Can't use ContainsText here - for group replacement this will always return true (group name is same EDID + '_Group')
// if ContainsText(EditorID(LLebi(aLevelList, i)), EditorID(aRecord)) then begin
if SameText(EditorID(LLelementbyindex(aLevelList, i)), EditorID(aRecord)) then
begin
{ Debug } if debugMsg then
addMessage('[LLcontains] if ' + EditorID(LLelementbyindex(aLevelList, i)) + ' = ' + EditorID(aRecord) + ' then begin');
{ Debug } if debugMsg then
addMessage('[LLcontains] Result := True');
result := true;
exit;
end;
end;
if debugMsg then
addMessage('[LLcontains] Result := False');
debugMsg := false;
// End debugMsg Section
end;
// Removes a LL entry; Returns removed element
function LLremove(aLevelList, aRecord): IInterface;
var
debugMsg: boolean;
i : integer;
begin
for i := 0 to Pred(LLec(aLevelList)) do
begin
if ContainsText(LLelementbyindex(aLevelList, i), EditorID(aRecord)) then
begin
result := LLelementbyindex(aLevelList, i);
Remove(elementbyindex(ElementByPath(aLevelList, 'Leveled List Entries'), i));
end;
end;
end;
// Finds the nth record in a level list
function IndexOfLL(aLevelList, aRecord): integer;
var
debugMsg: boolean;
i : integer;
begin
// Begin debugMsg Section
debugMsg := false;
result := false;
for i := 0 to Pred(LLec(aLevelList)) do
begin
if debugMsg then
addMessage('[IndexOfLL] if ' + GetElementEditValues(elementbyindex(ElementByPath(aLevelList, 'Leveled List Entries'), i), 'LVLO\Reference') + ', ' + ShortName(aRecord) + ' then begin');
if ContainsText(GetElementEditValues(elementbyindex(ElementByPath(aLevelList, 'Leveled List Entries'), i), 'LVLO\Reference'), EditorID(aRecord)) then
begin
result := i;
exit;
end;
end;
debugMsg := false;
// End debugMsg Section
end;
// Replaces aRecord with bRecord in aLevelList; Adds bRecord to aLevelList if aRecord is not detected; Returns true if replaced, false if added
function LLreplace(aLevelList, aRecord, bRecord: IInterface): boolean;
var
debugMsg: boolean;
i : integer;
begin
// Begin debugMsg Section
debugMsg := false;
result := false;
for i := 0 to Pred(LLec(aLevelList)) do
begin
{ Debug } if debugMsg then
addMessage('[LLreplace] ' + GetElementEditValues(elementbyindex(ElementByPath(aLevelList, 'Leveled List Entries'), i), 'LVLO\Reference'));
if ContainsText(GetElementEditValues(elementbyindex(ElementByPath(aLevelList, 'Leveled List Entries'), i), 'LVLO\Reference'), EditorID(aRecord)) then
begin
{ Debug } if debugMsg then
addMessage('[LLreplace] SetEditValue(' + GetElementEditValues(elementbyindex(ElementByPath(aLevelList, 'Leveled List Entries'), i), 'LVLO\Reference') + ', ' + ShortName(bRecord) + ');');
SetEditValue(ElementByPath(elementbyindex(ElementByPath(aLevelList, 'Leveled List Entries'), i), 'LVLO\Reference'), ShortName(bRecord));
{ Debug } if debugMsg then
addMessage('[LLreplace] ' + EditorID(LLelementbyindex(aLevelList, i)) + ' = ' + EditorID(aRecord));
exit;
end;
end;
// addToLeveledList(aLevelList, bRecord, 1);
// {Debug} if debugMsg then addMessage('[LLreplace] addToLeveledList('+EditorID(aLevelList)+', '+EditorID(bRecord)+', 1);');
debugMsg := false;
// End debugMsg Section
end;
// Check a records Flags for aFlag
function FlagCheck(aRecord: IInterface; aFlag: string): boolean;
var
debugMsg: boolean;
begin
result := false;
if ElementExists(aRecord, 'LVLF') then // If this record has a 'Flags' section
if ElementExists(ElementByPath(aRecord, 'LVLF'), aFlag) then // If this record has the flag, 'aFlag'
result := GetElementNativeValues(ElementByPath(aRecord, 'LVLF'), aFlag); // Return an integer value for this flag. IIRC it's a binary for Flag on/off
end;
// Creates new record inside provided file [Skyrim Utils]
function createRecord(recordFile: IwbFile; recordSignature: string): IInterface;
var
newRecordGroup: IInterface;
begin
newRecordGroup := GroupBySignature(recordFile, recordSignature);
if not Assigned(newRecordGroup) then
newRecordGroup := Add(recordFile, recordSignature, true);
result := Add(newRecordGroup, recordSignature, true);
end;
// Removes invalid entries from containers and recipe items, from Leveled lists, npcs and spells [SkyrimUtils]
procedure RemoveInvalidEntries(aRecord: IInterface);
var
record_sig, refName, countname: string;
aList, tempRecord : IInterface;
i, aList_ec : integer;
debugMsg : boolean;
begin
// Initialize
debugMsg := false;
// Process
record_sig := Signature(aRecord);
// Assign areas to look through given signature
if (record_sig = 'CONT') or (record_sig = 'COBJ') then
begin
aList := ElementByName(aRecord, 'Items');
refName := 'CNTO\Item';
countname := 'COCT';
end
else
if (record_sig = 'LVLI') or (record_sig = 'LVLN') or (record_sig = 'LVSP') then
begin
aList := ElementByName(aRecord, 'Leveled List Entries');
refName := 'LVLO\Reference';
countname := 'LLCT';
end
else
if (record_sig = 'OTFT') then
begin
aList := ElementByName(aRecord, 'INAM');
refName := 'item';
end
else
if (record_sig = 'ARMA') then
begin
aList := ElementByPath(aRecord, 'Additional Races');
end;
if not Assigned(aList) then
exit;
aList_ec := ElementCount(aList);
for i := aList_ec - 1 downto 0 do
begin
tempRecord := elementbyindex(aList, i);
{ Debug } if debugMsg then
addMessage('[removeInvalidEntries] aList tempRecord := ' + GetEditValue(tempRecord));
if (refName <> '') then
begin
if (Check(ElementByPath(tempRecord, refName)) <> '') then
Remove(tempRecord);
end else begin
if (GetEditValue(tempRecord) = 'NULL - Null Reference [00000000]') then
Remove(tempRecord);
end;
end;
if Assigned(countname) then
begin
if (aList_ec <> ElementCount(aList)) then
begin
aList_ec := ElementCount(aList);
if (aList_ec > 0) then
SetElementNativeValues(aRecord, countname, aList_ec)
else
RemoveElement(aRecord, countname);
end;
end;
end;
// Remove invalid entries from containers (experimental)
procedure removeErrors(aRecord: IInterface);
var
tempRecord, tempelement, currentElement: IInterface;
slProcess : TStringList;
debugMsg : boolean;
i, x : integer;
begin
// Initialize
debugMsg := false;
slProcess := TStringList.Create;
// Process
for i := 0 to Pred(ElementCount(aRecord)) do
slProcess.addObject(FullPath(elementbyindex(aRecord, i)), elementbyindex(aRecord, i));
while (slProcess.Count > 0) do
begin
tempelement := ObjectToElement(slProcess.Objects[0]);
{ Debug } if debugMsg then
addMessage('[removeErrors] tempElement := ' + name(tempelement));
for i := 0 to Pred(ElementCount(tempelement)) do
begin
currentElement := elementbyindex(tempelement, i);
{ Debug } if debugMsg then
addMessage('[removeErrors] currentElement := ' + name(currentElement));
{ Debug } if debugMsg then
addMessage('[removeErrors] if not ContainsText(' + GetEditValue(currentElement) + ', Error) then begin);');
if not ContainsText(GetEditValue(currentElement), 'Error') then
begin
if (ElementCount(currentElement) > 0) then
begin
{ Debug } if debugMsg then
addMessage('[removeErrors] slProcess.AddObject(' + name(currentElement) + ' );');
slProcess.addObject(FullPath(currentElement), currentElement);
end;
end else begin
if (name(currentElement) = 'Item') then
begin
addMessage('[removeErrors] ' + GetEditValue(currentElement) + ' Removed from ' + name(aRecord));
Remove(GetContainer(GetContainer(currentElement)));
end else begin
addMessage('[removeErrors] ' + GetEditValue(currentElement) + ' Removed from ' + name(aRecord));
Remove(currentElement);
end;
end;
end;
// {Debug} if debugMsg then addMessage('[removeErrors] slProcess.Delete('+slProcess[0]+' );');
slProcess.Delete(0);
end;
// Finalize
slProcess := TStringList.Create;
end;
// Adds item record reference to the list [SkyrimUtils]
function addItem(aRecord: IInterface; aItem: IInterface; aCount: integer): IInterface;
var
tempRecord: IInterface;
debugMsg : boolean;
begin
// Begin debugMsg section
debugMsg := false;
if not Assigned(ElementByPath(aRecord, 'Items')) then
Add(aRecord, 'Items', true);
tempRecord := ElementAssign(ElementByPath(aRecord, 'Items'), HighInteger, nil, false);
SetElementEditValues(tempRecord, 'CNTO - Item\Item', name(aItem));
SetElementEditValues(tempRecord, 'CNTO - Item\Count', aCount);
result := tempRecord;
debugMsg := false;
// End debugMsg section
end;
// Adds it
// Adds item reference to the leveled list [SkyrimUtils]
// nb097 - renamed tempBoolean to newList
function addToLeveledList(aLeveledList, aRecord: IInterface; aLevel: integer): IInterface;
var
tempRecord, currentList : IInterface;
i, tempInteger : integer;
tempString, previousRecord: string;
debugMsg, newList : boolean;
slTemp : TStringList;
begin
// Begin debugMgs section
debugMsg := true;
// nb097 - moved below line up so the debug message can show the editor ID of the current list
currentList := aLeveledList;
{ Debug } if debugMsg then
addMessage('[addToLeveledList] addToLeveledList(' + EditorID(currentList) + ', ' + EditorID(aRecord) + ', ' + IntToStr(aLevel) + ');');
slTemp := TStringList.Create;
slTemp.CommaText := '"Calculate from all levels <= player''s level", "Calculate for each item in count"';
// Check for leveled lists exceeding maximum entries
// nb097 - may not be necessary: changed to 200; to accommodate for other mods adding to LL's via scripts
while (LLec(currentList) >= 200) do
begin
// nb097 - reworked logic here to account for needing to expand beyond 9 lists
if StrEndsWithInteger(previousRecord) then
begin
if StrEndsWith(EditorID(currentList), '9') then
begin
// nb097 - Is the second to last character an integer?
if StrEndsWithInteger(RemoveFinalCharacter(EditorID(currentList))) then
begin
tempString := Copy(EditorID(currentList), Length(EditorID(currentList)) - 1, 2) + IntToStr((StrToInt(Copy(EditorID(currentList), Length(EditorID(currentList)) - 1, 2)) + 1));
// nb097 - If not, add '10'
end
else
tempString := EditorID(currentList) + '10';
end
else
tempString := RemoveFinalCharacter(EditorID(currentList)) + IntToStr((StrToInt(FinalCharacter(EditorID(currentList))) + 1));
end
else
tempString := EditorID(currentList) + '1';
{ Debug } if debugMsg then
addMessage('[addToLeveledList] addToLeveledList(' + EditorID(currentList) + ', ' + EditorID(aRecord) + ', ' + IntToStr(aLevel) + ') - tempString: ' + tempString);
tempRecord := MainRecordByEditorID(GroupBySignature(GetFile(currentList), 'LVLI'), tempString);
// nb097 - moved createLeveledList call out of if block; only create if not found
if Assigned(tempRecord) then
begin
{ Debug } if debugMsg then
addMessage('[addToLeveledList] addToLeveledList(' + EditorID(currentList) + ', ' + EditorID(aRecord) + ', ' + IntToStr(aLevel) + ') - LL: ' + tempString + ' found!');
currentList := tempRecord;
// nb097 - added renamed bool variable to signify new list or not
newList := false;
end else begin
currentList := createLeveledList(GetFile(currentList), tempString, slTemp, 0);
{ Debug } if debugMsg then
addMessage('[addToLeveledList] addToLeveledList(' + EditorID(currentList) + ', ' + EditorID(aRecord) + ', ' + IntToStr(aLevel) + ') - LL: ' + tempString + ' created!');
// nb097 - added renamed bool variable to signify new list or not
newList := true;
end;
// If a sequential leveled list is found or there's an infinite loop create a new leveled list
// nb097 - may not be necessary: changed to 200; to accommodate for other mods adding to LL's via scripts
if (LLec(currentList) <= 200) or (previousRecord = EditorID(currentList)) then
begin
// Remove trailing integers
while StrEndsWithInteger(tempString) do
begin
tempString := RemoveFinalCharacter(tempString);
end;
// Check for an existing group containing this leveled list
tempString := tempString + '_Group';
tempRecord := nil;
tempRecord := MainRecordByEditorID(GroupBySignature(GetFile(currentList), 'LVLI'), tempString);
// Add to exisitng group or create new group and run a replacement
if Assigned(tempRecord) then
begin
{ Debug } if debugMsg then
addMessage('[addToLeveledList] addToLeveledList(' + EditorID(currentList) + ', ' + EditorID(aRecord) + ', ' + IntToStr(aLevel) + ') - LL group: ' + tempString + ' found!');
// nb097 - if new list, THEN add to group, not always
if newList then
begin
addToLeveledList(tempRecord, currentList, 1);
{ Debug } if debugMsg then
addMessage('[addToLeveledList] addToLeveledList(' + EditorID(currentList) + ', ' + EditorID(aRecord) + ', ' + IntToStr(aLevel) + ') - LL group: ' + tempString + ' added ' + EditorID(currentList) + '!');
end;
end else begin
tempRecord := createLeveledList(GetFile(currentList), tempString, slTemp, 0);
{ Debug } if debugMsg then
addMessage('[addToLeveledList] addToLeveledList(' + EditorID(currentList) + ', ' + EditorID(aRecord) + ', ' + IntToStr(aLevel) + ') - LL group: ' + tempString + ' created!');
addToLeveledList(tempRecord, currentList, 1);
{ Debug } if debugMsg then
addMessage('[addToLeveledList] addToLeveledList(' + EditorID(currentList) + ', ' + EditorID(aRecord) + ', ' + IntToStr(aLevel) + ') - LL group: ' + tempString + ' added ' + EditorID(currentList) + '!');
addToLeveledList(tempRecord, aLeveledList, 1);
{ Debug } if debugMsg then
addMessage('[addToLeveledList] addToLeveledList(' + EditorID(currentList) + ', ' + EditorID(aRecord) + ', ' + IntToStr(aLevel) + ') - LL group: ' + tempString + ' added ' + EditorID(aLeveledList) + '!');
ReplaceInLeveledListAuto(aLeveledList, tempRecord, GetFile(aLeveledList));
{ Debug } if debugMsg then
addMessage('[addToLeveledList] addToLeveledList(' + EditorID(currentList) + ', ' + EditorID(aRecord) + ', ' + IntToStr(aLevel) + ') - LL group: ' + tempString + ' replaced ' + EditorID(aLeveledList) + ' with ' + EditorID(currentList) + '!');
end;
break;
end;
previousRecord := EditorID(currentList); // Prevent infinite loop
end;
slTemp.Free;
tempRecord := ElementAssign(ElementByPath(currentList, 'Leveled List Entries'), HighInteger, nil, false);
BeginUpdate(tempRecord);
try
SetElementEditValues(tempRecord, 'LVLO\Reference', name(aRecord));
SetElementEditValues(tempRecord, 'LVLO\Count', 1);
SetElementEditValues(tempRecord, 'LVLO\Level', aLevel);
finally
EndUpdate(tempRecord);
end;
result := tempRecord;
debugMsg := false;
// End debugMsg section
end;
// Creates COBJ record for item [SkyrimUtils]
function createRecipe(aRecord, aPlugin: IInterface): IInterface;
var
recipe: IInterface;
begin
recipe := createRecord(aPlugin, 'COBJ');
SetElementEditValues(recipe, 'CNAM', name(aRecord));
SetElementEditValues(recipe, 'NAM1', '1');
Add(aRecord, 'items', true);
result := recipe;
end;
// Gets an item type for slFuzzyItem
function GetItemType(aRecord: IInterface): string;
var
debugMsg : boolean;
slTemp, slBOD2: TStringList;
i : integer;
begin
// End debugMsg section
debugMsg := false;
// Initialize
{ Debug } if debugMsg then
addMessage('[GetItemType] GetItemType(' + EditorID(aRecord) + ' );');
slTemp := TStringList.Create;
slBOD2 := TStringList.Create;
// Function
if (Signature(aRecord) = 'WEAP') then
begin
slTemp.CommaText := 'Sword, Bow, WarAxe, Dagger, Greatsword, Mace, Warhammer, Battleaxe';
// Prioritize keywords
for i := 0 to slTemp.Count - 1 do
begin
if HasKeyword(aRecord, 'WeapType' + slTemp[i]) then
begin
result := slTemp[i];
if debugMsg then
addMessage('[GetItemType] ' + result + ' Detected');
slTemp.Free;
slBOD2.Free;
exit;
end;
end;
// Check edid/GetElementEditValues for keywords
for i := 0 to slTemp.Count - 1 do
begin
if ContainsText(GetElementEditValues(aRecord), slTemp[i]) or ContainsText(EditorID(aRecord), slTemp[i]) then
begin
// Exception for the string 'Sword' being within the string 'Greatsword'
if (slTemp[i] = 'Sword') then
if ContainsText(GetElementEditValues(aRecord), 'Greatsword') or ContainsText(EditorID(aRecord), 'Greatsword') then
Continue;
result := slTemp[i];
if debugMsg then
addMessage('[GetItemType] ' + result + ' Detected');
slTemp.Free;
slBOD2.Free;
exit;
end;
end;
// Broad Default values based on skill/animation style
if ContainsText(GetEditValue(ElementByPath(ElementBySignature(aRecord, 'DNAM'), 'Animation Type')), 'TwoHand') or ContainsText(GetEditValue(ElementByPath(ElementBySignature(aRecord, 'DNAM'), 'Skill')), 'TwoHand') then
begin
result := slTemp[slTemp.Count - 1];
end
else
if ContainsText(GetEditValue(ElementByPath(ElementBySignature(aRecord, 'DNAM'), 'Animation Type')), 'Bow') or ContainsText(GetEditValue(ElementByPath(ElementBySignature(aRecord, 'DNAM'), 'Skill')), 'Archery') then
begin
result := slTemp[1];
end else begin
result := slTemp[0];
end;
end
else
if (Signature(aRecord) = 'AMMO') then
begin
// Get selected record type
slTemp.CommaText := 'Arrow, Bolt';
// Prioritize keywords
for i := 0 to slTemp.Count - 1 do
begin
if HasKeyword(aRecord, 'WeapType' + slTemp[i]) then
begin
result := slTemp[i];
if debugMsg then
addMessage('[GetItemType] ' + result + ' Detected');
slTemp.Free;
slBOD2.Free;
exit;
end;
end;
// Check edid/GetElementEditValues for keywords
for i := 0 to slTemp.Count - 1 do
begin
if ContainsText(GetElementEditValues(aRecord), slTemp[i]) or ContainsText(EditorID(aRecord), slTemp[i]) then
begin
result := slTemp[i];
if debugMsg then
addMessage('[GetItemType] ' + result + ' Detected');
slTemp.Free;
slBOD2.Free;
exit;
end;
end;
// Broad default value
result := slTemp[0];
end
else
if (Signature(aRecord) = 'ARMO') then
begin
// '30, 32, 33, 37, 39'; // 30 - Head, 32 - Body, 33 - Gauntlers, 37 - Feet, 39 - Shield
slGetFlagValues(aRecord, slBOD2, false);
{ Debug } if debugMsg then
msgList('[Tier Assignment] slBOD2 := ', slBOD2, '');
slTemp.CommaText := '30, 32, 33, 37, 39, 35, 36, 42'; // 30 - Head, 32 - Body, 33 - Gauntlets, 37 - Feet, 39 - Shield, 35 - Necklace, 36 - Ring, 42 - Circlet
// For vanilla slots
for i := 0 to slTemp.Count - 1 do
begin
if slContains(slBOD2, slTemp[i]) then
begin
// This 'if' covers certain mods that change helmet BOD2
if (slTemp[i] = '42') then
if Assigned(ElementByPath(aRecord, 'DNAM')) then
if (GetElementEditValues(aRecord, 'DNAM') > 0) then
result := '30';
if not Assigned(result) then
result := slTemp[i];
break;
end;
end;
// Non-vanilla slots prioritize keywords
if debugMsg then
addMessage('[GetItemType] Non-vanilla slots prioritize keywords');
if (result = '') then
begin
{ Debug } if debugMsg then
addMessage('[GetTemplate] Check Keywords');
for i := 0 to Pred(ElementCount(ElementByPath(aRecord, 'KWDA'))) do
begin
{ Debug } if debugMsg then
addMessage('[GetTemplate] Keyword := ' + GetEditValue(elementbyindex(ElementByPath(aRecord, 'KWDA'), i)));
result := KeywordToBOD2(GetEditValue(elementbyindex(ElementByPath(aRecord, 'KWDA'), i)));
if (result <> '') then
break;
end;
end;
// Default BOD2 for items without keywords
if debugMsg then
addMessage('[GetItemType] Default BOD2 for items without keywords');
if (result = '') then
begin
{ Debug } if debugMsg then
addMessage('[GetTemplate] Check Non-Vanilla BOD2');
// Helmet
slTemp.CommaText := '31, 41, 55, 130, 131, 141, 150, 230';
for i := 0 to slTemp.Count - 1 do
if slContains(slBOD2, slTemp[i]) then
result := '30';
// Body
slTemp.CommaText := '38, 40, 46, 49, 52, 53, 54, 56';
for i := 0 to slTemp.Count - 1 do
if slContains(slBOD2, slTemp[i]) then
result := '32';
// Gauntlets
slTemp.CommaText := '38, 58, 57, 59';
for i := 0 to slTemp.Count - 1 do
if slContains(slBOD2, slTemp[i]) then
result := '37';
// Boots
slTemp.CommaText := '34';
for i := 0 to slTemp.Count - 1 do
if slContains(slBOD2, slTemp[i]) then
result := '33';
// Circlet
slTemp.CommaText := '43, 142';
for i := 0 to slTemp.Count - 1 do
begin
if slContains(slBOD2, slTemp[i]) then
begin
result := '42';
if Assigned(ElementByPath(aRecord, 'DNAM')) then
if (GetElementEditValues(aRecord, 'DNAM') > 0) then
result := '30';
end;
end;
// Necklace
slTemp.CommaText := '44, 45, 47, 143';
for i := 0 to slTemp.Count - 1 do
if slContains(slBOD2, slTemp[i]) then
result := '35';
// Ring
slTemp.CommaText := '48, 60';
for i := 0 to slTemp.Count - 1 do
if slContains(slBOD2, slTemp[i]) then
result := '36';
end;
// Convert BOD2 to EditorID
{ Debug } if debugMsg then
addMessage('[GetTemplate] Convert BOD2 to EditorID');
slTemp.CommaText := '30-Helmet, 32-Cuirass, 33-Gauntlets, 37-Boots, 39-Shield, 35-Necklace, 36-Ring, 42-Circlet'; // 30 - Head, 32 - Body, 33 - Gauntlets, 37 - Feet, 39 - Shield, 35 - Necklace, 36 - Ring, 42 - Circlet
for i := 0 to slTemp.Count - 1 do
begin
if ContainsText(slTemp[i], result) then
begin
result := StrPosCopy(slTemp[i], '-', false);
// addMessage('['+GetElementEditValues(aRecord)+'] '+Result+' Detected');
break;
end;
end;
end;
// Finalize
slTemp.Free;
debugMsg := false;
// End debugMsg section
end;
// Reduces a BOD2 to an associated BOD2
function AssociatedBOD2(aString: string): string;
var
slTemp: TStringList;
i : integer;
begin
slTemp := TStringList.Create;
result := aString;
// Helmet
slTemp.CommaText := '31, 41, 55, 130, 131, 141, 150, 230';
for i := 0 to slTemp.Count - 1 do
if (aString = slTemp[i]) then
result := '30';
// Body
slTemp.CommaText := '38, 40, 46, 49, 52, 53, 54, 56';
for i := 0 to slTemp.Count - 1 do
if (aString = slTemp[i]) then
result := '32';
// Gauntlets
slTemp.CommaText := '38, 58, 57, 59';
for i := 0 to slTemp.Count - 1 do
if (aString = slTemp[i]) then
result := '37';
// Boots
slTemp.CommaText := '34';
for i := 0 to slTemp.Count - 1 do
if (aString = slTemp[i]) then
result := '33';
// Circlet
slTemp.CommaText := '43, 142';
for i := 0 to slTemp.Count - 1 do
if (aString = slTemp[i]) then
result := '42';
// Necklace
slTemp.CommaText := '44, 45, 47, 143';
for i := 0 to slTemp.Count - 1 do
if (aString = slTemp[i]) then
result := '35';
// Ring
slTemp.CommaText := '48, 60';
for i := 0 to slTemp.Count - 1 do
if (aString = slTemp[i]) then
result := '36';
slTemp.Free;
end;
// Takes a single armor keyword and returns a list of all keywords related to it
procedure slFuzzyItem(aString: string; aList: TStringList);
var
slTemp : TStringList;
debugMsg: boolean;
i : integer;
begin
// Begin debugMsg Section
debugMsg := false;
// Initialize
{ Debug } if debugMsg then
addMessage('[slFuzzyItem] inputString := ' + aString);
if not Assigned(slTemp) then
slTemp := TStringList.Create
else
slTemp.clear;
// Function
slTemp.CommaText := 'Helmet, Crown, Helm, Hood, Mask, Circlet, Headdress';
for i := 0 to slTemp.Count - 1 do
if aString = slHelmet[i] then
if not slContains(aList, slHelmet[i]) then
aList.Add(slHelmet[i]);
slTemp.CommaText := 'Bracers, Gloves, Gauntlets';
for i := 0 to slTemp.Count - 1 do
if aString = slGauntlets[i] then
if not slContains(aList, slGauntlets[i]) then
aList.Add(slGauntlets[i]);
slTemp.CommaText := 'Boots, Shoes';
for i := 0 to slTemp.Count - 1 do
if aString = slBoots[i] then
if not slContains(aList, slBoots[i]) then
aList.Add(slBoots[i]);
slTemp.CommaText := 'Cuirass, Armor';
for i := 0 to slTemp.Count - 1 do
if aString = slCuirass[i] then
if not slContains(aList, slCuirass[i]) then
aList.Add(slCuirass[i]);
slTemp.CommaText := 'Shield, Buckler';
for i := 0 to slTemp.Count - 1 do
if aString = slShield[i] then
if not slContains(aList, slShield[i]) then
aList.Add(slShield[i]);
{ Debug } if debugMsg then
msgList('[slFuzzyItem] Result := ', aList, '');
// '30, 32, 33, 37, 39'; // 30 - Head, 32 - Body, 33 - Gauntlers, 37 - Feet, 39 - Shield
// Finalize
slTemp.Free;
debugMsg := false;
// End debugMsg Section
end;
// Reduces a list of armor keywords into a single armor keyword
function GetFuzzyItem(aString: string): string;
var
slTemp : TStringList;
debugMsg: boolean;
i : integer;
begin
// Begin debugMsg Section
debugMsg := false;
// Initialize
{ Debug } if debugMsg then
addMessage('[slFuzzyItem] inputString := ' + aString);
if not Assigned(slTemp) then
slTemp := TStringList.Create
else
slTemp.clear;
// Function
slTemp.CommaText := 'Helmet, Crown, Helm, Hood, Mask, Circlet, Headdress';
for i := 0 to slTemp.Count - 1 do
if aString = slHelmet[i] then
begin
result := 'Helmet';
slTemp.Free;
exit;
end;
slTemp.CommaText := 'Bracers, Gloves, Gauntlets, claws';
for i := 0 to slTemp.Count - 1 do
if aString = slGauntlets[i] then
begin
result := 'Gauntlets';
slTemp.Free;
exit;
end;
slTemp.CommaText := 'Boots, Shoes';
for i := 0 to slTemp.Count - 1 do
if aString = slBoots[i] then
begin
result := 'Boots';
slTemp.Free;
exit;
end;
slTemp.CommaText := 'Cuirass, Armor';
for i := 0 to slTemp.Count - 1 do
if aString = slCuirass[i] then
begin
result := 'Cuirass';
slTemp.Free;
exit;
end;
slTemp.CommaText := 'Shield, Buckler';
for i := 0 to slTemp.Count - 1 do
if aString = slShield[i] then
begin
result := 'Shield';
slTemp.Free;
exit;
end;
{ Debug } if debugMsg then
msgList('[slFuzzyItem] Result := ', aList, '');
// Finalize
if Assigned(slTemp) then
slTemp.Free;
debugMsg := false;
// End debugMsg Section
end;
// Adds a TStringList to an addMessage on a single line
procedure msgList(s1: string; aList: TStringList; s2: string);
var
debugMsg : boolean;
i : integer;
tempString: string;
begin
// Begin debugMsg section
debugMsg := false;
if not Assigned(aList) or (aList.Count = 0) then
begin
addMessage(s1 + 'EMPTY LIST' + s2);
exit;
end;
for i := 0 to aList.Count - 1 do
begin
if (i = 0) then
begin
tempString := aList[0];
end else begin
tempString := tempString + ', ' + aList[i];
end;
end;
addMessage(s1 + tempString + s2);
debugMsg := false;
// End debugMsg section
end;
// Adds a TStringList and its objects to an addMessage on a single line
procedure msgListObject(s1: string; aList: TStringList; s2: string);
var
debugMsg : boolean;
i : integer;
tempString: string;
begin
// Begin debugMsg section
debugMsg := false;
//addmessage(VarTypeAsText(aList));
if not Assigned(aList) or (aList.Count = 0) then
begin
addMessage(s1 + 'EMPTY LIST' + s2);
exit;
end;
for i := 0 to aList.Count - 1 do
begin
if (i = 0) then
begin
tempString := aList[0];
end else begin
tempString := tempString + ', ' + aList[i] + ' (' + varTypeAsText(aList.Objects[i]) + ')';
end;
end;
addMessage(s1 + tempString + s2);
debugMsg := false;
// End debugMsg section
end;
// Trims all the string in a list
function TrimList(aList: TStringList): TStringList;
var
debugMsg: boolean;
i : integer;
begin
for i := 0 to aList.Count - 1 do
aList[i] := Trim(aList[i]);
result := aList;
end;
// Gets ElementCount of the Leveled List Entries
function LLec(e: IInterface): integer;
begin
result := ElementCount(ElementByPath(e, 'Leveled List Entries'));
end;
// Gets record from leveled list index
function LLelementbyindex(e: IInterface; i: integer): IInterface;
var
debugMsg: boolean;
begin
// Begin debugMsg section
debugMsg := false;
{ Debug } if debugMsg then
addMessage('[LLelementbyindex] e := ' + EditorID(e));
// {Debug} if debugMsg then addMessage('[LLelementbyindex] elementbyindex := '+GetElementEditValues(elementbyindex(ElementByPath(e, 'Leveled List Entries'), i), 'LVLO\Reference'));
{ Debug } if debugMsg then
addMessage('[LLelementbyindex] Result := ' + EditorID(LinksTo(ElementByPath(elementbyindex(ElementByPath(e, 'Leveled List Entries'), i), 'LVLO\Reference'))));
result := LinksTo(ElementByPath(elementbyindex(ElementByPath(e, 'Leveled List Entries'), i), 'LVLO\Reference'));
debugMsg := false;
// End debugMsg section
end;
// Removes any file suffixes from a File Name
function RemoveFileSuffix(inputString: string): string;
var
slTemp : TStringList;
debugMsg: boolean;
i : integer;
begin
// Begin debugMsg Section
debugMsg := false;
// Initialize
{ Debug } if debugMsg then
addMessage('[RemoveFileSuffix] inputString := ' + inputString);
if not Assigned(slTemp) then
slTemp := TStringList.Create
else
slTemp.clear;
// Function
result := inputString;
slTemp.CommaText := '.esp, .esm, .exe, .esl';
for i := 0 to slTemp.Count - 1 do
begin
{ Debug } if debugMsg then
addMessage('[RemoveFileSuffix] if StrEndsWith(inputString, ' + slTemp[i] + ') := ' + BoolToStr(StrEndsWith(inputString, slTemp[i])));
if StrEndsWith(inputString, slTemp[i]) then
begin
result := RemoveFromEnd(inputString, slTemp[i]);
{ Debug } if debugMsg then
addMessage('[RemoveFileSuffix] Result := ' + inputString);
exit;
end;
end;
// Finalize
slTemp.Free;
debugMsg := false;
// End debugMsg Section
end;
// Removes duplicate strings in a TStringList
procedure slRemoveDuplicates(aList: TStringList);
var
i : integer;
slTemp: TStringList;
begin
// Initialize
slTemp := TStringList.Create;
// Function
for i := 0 to aList.Count - 1 do
if not slContains(slTemp, aList[i]) then
slTemp.Add(aList[i]);
if (slTemp.Count > 0) then
begin
aList.Assign(slTemp);
end;
// Finalize
slTemp.Free;
end;
// Creates a % Chance Leveled List
function createChanceLeveledList(aPlugin: IInterface; aName: string; Chance: integer; aRecord, aLevelList: IInterface): IInterface;
var
chanceLevelList, nestedChanceLevelList: IInterface;
debugMsg, tempBoolean : boolean;
i, tempInteger : integer;
slTemp : TStringList;
begin
// Begin debugMsg section
debugMsg := false;
// The following section can be real confusing without examples.
// If I have a 10% chance I need a Leveled List with 9 copies of the regular item and 1 copy of the enchantment Leveled List. In math this looks like 1/10 = 10/100 = 10%.
// If I have a 9% chance I need a Leveled List (List A) with 9 copies of the regular item and 1 copy of the enchantment Leveled List.
// I also need ANOTHER list (List B) with 9 copies of the regular item and 1 copy of List A. In math this looks like 1/10 * 9/10 = 9/100 (or 9%).
// Similarly, if I have an 11% chance I need a Leveled List (List A) with 9 copies of the regular item and 1 copy of the enchantment Leveled List.
// I also need ANOTHER list with 8 copies of the regular item, 1 copy of List A, and 1 copy of the enchantment list. In math this looks like 1/10 + (1/10 * 9/10) = 11/100 (or 11%).
// Initialize
if Chance = 0 then
exit;
slTemp := TStringList.Create;
// Create %chance list
slTemp.CommaText := '"Calculate from all levels <= player''s level", "Calculate for each item in count"';
chanceLevelList := createLeveledList(aPlugin, aName, slTemp, 0);
// If it's a 100% chance we just need a single leveled list
if Chance = 100 then
begin { Debug }
if debugMsg then
addMessage('[%Chance] Chance = 100; Removing chanceLevelList and assigning aLevelList to chanceLevelList for AddToLeveledListAuto input');
Remove(chanceLevelList);
chanceLevelList := aLevelList;
end
else
if (Length(IntToStr(Chance)) = 1) then
begin { Debug }
if debugMsg then
addMessage('[%Chance] for i := 0 to Chance do addToLeveledList(' + EditorID(nestedChanceLevelList) + ', ' + EditorID(aLevelList) + ', 1 );');
for i := 0 to Chance do
addToLeveledList(nestedChanceLevelList, aLevelList, 1); { Debug }
if debugMsg then
addMessage('[%Chance] while (LLec(nestedChanceLevelList) < 10) do addToLeveledList(' + EditorID(nestedChanceLevelList) + ', ' + EditorID(aRecord) + ', 1 );');
while (LLec(nestedChanceLevelList) < 10) do
addToLeveledList(nestedChanceLevelList, aRecord, 1);
addToLeveledList(chanceLevelList, nestedChanceLevelList, 1);
{ Debug } if debugMsg then
addMessage('[%Chance] while (LLec(' + EditorID(chanceLevelList) + ' ) < 10) do addToLeveledList(' + EditorID(chanceLevelList) + ', ' + EditorID(aRecord) + ', 1 );');
while (LLec(chanceLevelList) < 10) do
addToLeveledList(chanceLevelList, aRecord, 1);
end else begin
// Grab the second digit; If the second digit is 0 we don't need the nested leveled list; Example: 10, 20, 30, etc.
{ Debug } if debugMsg then
addMessage('[%Chance] StrToInt(Copy(IntToStr(Chance), 2, 1)) := ' + Copy(IntToStr(Chance), 2, 1));
tempInteger := StrToInt(Copy(IntToStr(Chance), 2, 1));
if (tempInteger = 0) then
tempBoolean := true
else
tempBoolean := false;
{ Debug } if debugMsg then
addMessage('[%Chance] tempBoolean := ' + BoolToStr(tempBoolean));
// Grab the first digit
{ Debug } if debugMsg then
addMessage('[%Chance] StrToInt(Copy(IntToStr(Chance), 1, 1)) := ' + Copy(IntToStr(Chance), 1, 1));
tempInteger := StrToInt(Copy(IntToStr(Chance), 1, 1));
// Create the percent chance leveled list for 10, 20, 30, etc. (numbers that don't need the nested leveled list)
if tempBoolean then
begin { Debug }
if debugMsg then
addMessage('[%Chance] if tempBoolean then begin for i := 0 to tempInteger-1 := ' + IntToStr(tempInteger - 1) + ' do addToLeveledList(' + EditorID(chanceLevelList) + ', ' + EditorID(aLevelList) + ', 1 ); while (LLec(chanceLevelList) :=' + IntToStr(LLec(chanceLevelList)) + ' < 10) do addToLeveledList(' + EditorID(chanceLevelList) + ', ' + EditorID(aRecord) + ', 1 );');
for i := 0 to tempInteger - 1 do
addToLeveledList(chanceLevelList, aLevelList, 1);
while (LLec(chanceLevt) < 10) do
addToLeveledList(chanceLevelList, aRecord, 1);
end else begin { Debug }
if debugMsg then
addMessage('[%Chance] Not tempBoolean; Beginning nested list generation');
// Create a nested leveled list for valid integers between 0 and 100 with a second digit greater than 0. Example: 51, 52, 53, etc.
{ Debug } if debugMsg then
addMessage('[%Chance] Creating and preparing nestedchanceLevelList');
nestedChanceLevelList := createLeveledList(aPlugin, Insert('nested', aName, ItPos(aName, 'e', 3)), slTemp, 0);
// Fill the nested and chance leveled lists based on Chance
for i := 0 to (StrToInt(Copy(IntToStr(Chance), 2, 1)) - 1) do
addToLeveledList(nestedChanceLevelList, aLevelList, 1);
while (LLec(nestedChanceLevelList) < 10) do
addToLeveledList(nestedChanceLevelList, aRecord, 1);
addToLeveledList(chanceLevelList, nestedChanceLevelList, 1);
for i := 0 to tempInteger - 1 do
addToLeveledList(chanceLevelList, aLevelList, 1);
while (LLec(chanceLevelList) < 10) do
addToLeveledList(chanceLevelList, aRecord, 1);
end;
end;
result := chanceLevelList;
// Finalize
slTemp.Free;
debugMsg := false;
// End debugMsg section
end;
// Only first letter capitalized
function StrCapFirst(str: string): string;
var
str, format_str: string;
debugMsg : boolean;
begin
// Begin debugMsg section
debugMsg := false;
{ Debug } if debugMsg then
addMessage('[StrCapFirst] ' + Uppercase(Copy(str, 1, 1)) + LowerCase(Copy(str, 2, Length(str))));
result := Uppercase(Copy(str, 1, 1)) + LowerCase(Copy(str, 2, Length(str)));
debugMsg := false;
// End debugMsg section
end;
// Finds a TForm element by name
function ComponentByCaption(aString: string; aForm: TForm): TObject;
var
debugMsg: boolean;
i : integer;
begin
// Begin debugMsg section
debugMsg := false;
{ Debug } if debugMsg then
addMessage('[ComponentByCaption] aString := ' + aString);
for i := aForm.ComponentCount - 1 downto 0 do
begin
if (aForm.Components[i].Caption = aString) then
begin
result := aForm.Components[i];
exit;
end;
end;
debugMsg := false;
// End debugMsg Section
end;
// Finds a TForm element by name
function ComponentByTop(aTop: integer; aForm: TObject): TObject;
var
debugMsg: boolean;
i : integer;
begin
// Begin debugMsg section
debugMsg := false;
for i := aForm.ComponentCount - 1 downto 0 do
begin
if (aForm.Components[i].Top = aTop) then
begin
result := aForm.Components[i];
exit;
end;
end;
debugMsg := false;
// End debugMsg Section
end;
// Caption Exists on TForm element
function CaptionExists(aString: string; aForm: TObject): boolean;
var
Form : TForm;
debugMsg: boolean;
i : integer;
begin
// Begin debugMsg section
debugMsg := false;
result := false;
for i := aForm.ComponentCount - 1 downto 0 do
begin
{ Debug } if debugMsg then
addMessage('[CaptionExists] if (' + aForm.Components[i].Caption + ' = ' + aString + ' ) then begin');
if (aForm.Components[i].Caption = aString) then
begin
result := true;
end;
end;
{ Debug } if debugMsg then
addMessage('[CaptionExists] Result := ' + BoolToStr(result));
debugMsg := false;
// End debugMsg section
end;
// Finds the longest common substring
function LongestCommonString(aList: TStringList): string;
var
i, x, y, z: integer;
tempString: string;
slTemp : TStringList;
debugMsg : boolean;
begin
// Begin debugMsg section
debugMsg := false;
// Initialize Local
slTemp := TStringList.Create;
// Function
for i := 0 to aList.Count - 1 do
begin
tempString := nil;
slTemp.CommaText := aList[i];
{ Debug } if debugMsg then
msgList('[LongestCommonString] slTemp := ', slTemp, '');
for x := slTemp.Count - 1 downto 0 do
begin
tempString := nil;
for y := 0 to x do
tempString := Trim(tempString + ' ' + slTemp[y]);
for y := 0 to aList.Count - 1 do
begin
{ Debug } if debugMsg then
addMessage('[LongestCommonString] ContainsText(' + aList[y] + ', ' + tempString + ' )');
if ContainsText(aList[y], tempString) and (y <> i) then
begin
if Assigned(result) then
begin
if (Length(tempString) > Length(result)) then
result := tempString;
end else begin
result := tempString;
end;
end;
end;
end;
end;
if not Assigned(result) then
result := aList[0];
// Finalize Local
slTemp.Free;
debugMsg := false;
// End debugMsg section
end;
function DecToRoman(Decimal: integer): string;
var
slNumbers, slRomans: TStringList;
i : integer;
begin
// Initialize
slNumbers := TStringList.Create;
slRomans := TStringList.Create;
slNumbers.CommaText := '1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000';
slRomans.CommaText := 'I, IV, V, IX, X, XL, L, XC, C, CD, D, CM, M';
result := '';
for i := 12 downto 0 do
begin
while (Decimal >= slNumbers[i]) do
begin
Decimal := Decimal - slNumbers[i];
result := result + slRomans[i];
end;
end;
// Finalization
slNumbers.Free;
slRomans.Free;
end;
// [FUNCTIONS SPECIFIC TO GENERATEENCHANTEDVERSIONSAUTO]
procedure Btn_Bulk_OnClick(Sender: TObject);
var
lblAddPlugin, lblDetectedFileText, lblHelp : TLabel;
tempComponent, btnAdd, btnOk, btnCancel, btnRemove: TButton;
ddAddPlugin, ddDetectedFile : TComboBox;
slTemp, slFiles : TStringList;
ALLAfile, tempFile, tempRecord : IInterface;
frm : TForm;
exist, debugMsg : boolean;
ALLAplugin : string;
i, x, y : integer;
begin
// Begin debugMsg section
debugMsg := false;
// Initialize
slFiles := TStringList.Create;
slTemp := TStringList.Create;
frm := Sender.Parent;
tempComponent := AssociatedComponent('Output Plugin: ', Sender.Parent);
ALLAplugin := tempComponent.Caption;
if not StrEndsWith(ALLAplugin, '.esl') or StrEndsWith(ALLAplugin, '.exe') or StrEndsWith(ALLAplugin, '.exe') then
AppendIfMissing(ALLAplugin, '.esp');
exist := false;
ALLAfile := FileByName(ALLAplugin, exist);
if not exist then begin
if MessageDlg('Create a new plugin named ' + ALLAplugin + ' [YES] or cancel [NO]?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then
begin
AddNewFileName(ALLAplugin);
end
else
exit;
end;
// Dialogue Box
frm := TForm.Create(nil);
try
// Remove all previous TForm components
btnOk := nil;
btnCancel := nil;
// Parent Form; Entire Box
frm.Width := 850;
frm.Height := 200;
frm.Position := poScreenCenter;
frm.Caption := 'Process Plugins in Bulk';
// Currently Selected File Label
lblDetectedFileText := TLabel.Create(frm);
lblDetectedFileText.Parent := frm;
lblDetectedFileText.Height := 24;
lblDetectedFileText.Top := 68;
lblDetectedFileText.Left := 60;
lblDetectedFileText.Caption := 'Output File: ';
frm.Height := frm.Height + lblDetectedFileText.Height + 12;
// Currently Selected File
ddDetectedFile := TComboBox.Create(frm);
ddDetectedFile.Parent := frm;
ddDetectedFile.Height := lblDetectedFileText.Height;
ddDetectedFile.Top := lblDetectedFileText.Top;
ddDetectedFile.Left := 205;
ddDetectedFile.Width := 480;
ddDetectedFile.Items.Add(ALLAplugin);
ddDetectedFile.ItemIndex := 0;
// Add Plugin Label
lblAddPlugin := TLabel.Create(frm);
lblAddPlugin.Parent := frm;
lblAddPlugin.Height := lblDetectedFileText.Height;
lblAddPlugin.Top := lblDetectedFileText.Top + lblDetectedFileText.Height + 24;
lblAddPlugin.Left := lblDetectedFileText.Left;
lblAddPlugin.Caption := 'Add Plugin: ';
frm.Height := frm.Height + lblAddPlugin.Height + 12;
// Add Plugin Drop Down
ddAddPlugin := TComboBox.Create(frm);
ddAddPlugin.Parent := frm;
ddAddPlugin.Height := lblAddPlugin.Height;
ddAddPlugin.Top := lblAddPlugin.Top - 2;
ddAddPlugin.Left := ddDetectedFile.Left;
ddAddPlugin.Width := 480;
for i := 0 to FileCount - 1 do
if not(StrEndsWith(GetFileName(FileByIndex(i)), '.exe') or slContains(slGlobal, GetFileName(FileByIndex(i)))) then
ddAddPlugin.Items.Add(GetFileName(FileByIndex(i)));
ddAddPlugin.AutoComplete := true;
// Add Button
btnAdd := TButton.Create(frm);
btnAdd.Parent := frm;
btnAdd.Caption := 'Add';
btnAdd.Left := ddAddPlugin.Left + ddAddPlugin.Width + 8;
btnAdd.Top := lblAddPlugin.Top;
btnAdd.Width := 100;
btnAdd.OnClick := Btn_AddOrRemove_OnClick;
// Ok Button
btnOk := TButton.Create(frm);
btnOk.Parent := frm;
btnOk.Caption := 'Ok';
btnOk.Left := (frm.Width div 2) - btnOk.Width - 8;
btnOk.Top := frm.Height - 80;
btnOk.ModalResult := mrOk;
// Cancel Button
btnCancel := TButton.Create(frm);
btnCancel.Parent := frm;
btnCancel.Caption := 'Cancel';
btnCancel.Left := btnOk.Left + btnOk.Width + 16;
btnCancel.Top := btnOk.Top;
btnCancel.ModalResult := mrCancel;
frm.ShowModal;
// Displays a help message
if (frm.ModalResult = mrOk) and (ddAddPlugin.Text <> '') and not CaptionExists('Remove', frm) then
begin
lblHelp := TLabel.Create(frm);
lblHelp.Parent := frm;
lblHelp.Height := 24;
lblHelp.Top := btnAdd.Top + btnAdd.Height + 8;
lblHelp.Left := btnAdd.Left - 50;
lblHelp.Caption := 'USE ADD BUTTON';
frm.ShowModal;
end;
if (frm.ModalResult = mrOk) then
begin
// If list is empty
if not CaptionExists('Remove', frm) then
exit;
// Output
for i := 0 to slGlobal.Count - 1 do
if ContainsText(slGlobal[i], 'Original') or ContainsText(slGlobal[i], 'Template') then
slTemp.Add(slGlobal[i]);
for i := 0 to slTemp.Count - 1 do
if (slGlobal.IndexOf(slTemp[i]) >= 0) then
slGlobal.Delete(slGlobal.IndexOf(slTemp[i]));
slFiles.Assign(slGlobal);
// Sender.Parent.Visible := False;
tempComponent.Caption := ddDetectedFile.Text;
slTemp.CommaText := 'ARMO, AMMO, WEAP';
{ Debug } if debugMsg then
msgList('[ELLR_Bulk_OnClick] slFiles := ', slFiles, '');
for i := 0 to slFiles.Count - 1 do
begin
{ Debug } if debugMsg then begin
exist := false;
FileByName(slFiles[i], exist);
addMessage('[ELLR_Bulk_OnClick] if FileByName(' + slFiles[i] + ' ) := ' + BoolToStr(exist) + ' then begin');
end;
if exist then
begin
tempFile := FileByName(slFiles[i]);
{ Debug } if debugMsg then
addMessage('[ELLR_Bulk_OnClick] tempFile := ' + GetFileName(tempFile));
{ Debug } if debugMsg then
addMessage('[ELLR_Bulk_OnClick] for x := 0 to slTemp.Count-1 := ' + IntToStr(slTemp.Count - 1) + ' do begin');
for x := 0 to slTemp.Count - 1 do
begin
{ Debug } if debugMsg then
addMessage('[ELLR_Bulk_OnClick] for y := 0 to Pred(ElementCount(GroupBySignature(' + GetFileName(tempFile) + ', ' + slTemp[x] + ' ))) := ' + IntToStr(Pred(ElementCount(GroupBySignature(ObjectToElement(slFiles.Objects[i]), slTemp[x])))) + ' do begin');
for y := 0 to Pred(ElementCount(GroupBySignature(tempFile, slTemp[x]))) do
begin
{ Debug } if debugMsg then
addMessage('[ELLR_Bulk_OnClick] tempRecord := elementbyindex(GroupBySignature(' + GetFileName(tempFile) + ', ' + slTemp[x]'+), ' + IntToStr(x) + ' );');
tempRecord := elementbyindex(GroupBySignature(tempFile, slTemp[x]), y);
if not(Length(EditorID(tempRecord)) > 0) then
Continue;
{ Debug } if debugMsg then
addMessage('[ELLR_Bulk_OnClick] tempRecord := ' + EditorID(tempRecord));
if not slContains(slGlobal, EditorID(tempRecord)) then
begin
slGlobal.addObject(EditorID(tempRecord) + 'Original', tempRecord);
slGlobal.addObject(EditorID(tempRecord) + 'Template', GetTemplate(tempRecord));
end;
end;
end;
end;
end;
{ Debug } if debugMsg then
msgList('[ELLR_Bulk_OnClick] slGlobal := ', slGlobal, '');
Sender.Parent.ModalResult := mrOk;
end else begin
tempComponent.Caption := ddDetectedFile.Text;
slTemp.clear;
for i := 0 to slGlobal.Count - 1 do begin
exist := false;
FileByName(slGlobal[i], exist);
if exist then
slTemp.Add(slGlobal[i]);
end;
for i := 0 to slTemp.Count - 1 do
if (slGlobal.IndexOf(slTemp[i]) >= 0) then
slGlobal.Delete(slGlobal.IndexOf(slTemp[i]));
end;
finally
frm.Free;
end;
// Finalize
slFiles.Free;
slTemp.Free;
debugMsg := false;
// End debugMsg Section
end;
procedure Btn_AddOrRemove_OnClick(Sender: TObject);
var
btnAdd, btnRemove, btnOk, btnCancel: TButton;
tempBoolean, debugMsg, exist : boolean;
lblPlugin : TLabel;
i, tempInteger : integer;
tempPlugin : string;
GEVfile : IInterface;
frm : TForm;
begin
// Begin debugMsg section
debugMsg := false;
// Grab values from parent form
frm := Sender.Parent;
if CaptionExists('Remove Plugin: ', frm) then
begin
tempPlugin := AssociatedComponent('Remove Plugin: ', frm).Caption;
{ Debug } if debugMsg then
addMessage('[Btn_AddOrRemove_OnClick] tempPlugin := ' + tempPlugin);
end
else
if CaptionExists('Add Plugin: ', frm) then
begin
tempPlugin := AssociatedComponent('Add Plugin: ', frm).Caption;
{ Debug } if debugMsg then
addMessage('[Btn_AddOrRemove_OnClick] tempPlugin := ' + tempPlugin);
end;
// Manipulate static list of added values
{ Debug } if debugMsg then
addMessage('[Btn_AddOrRemove_OnClick] TLabel(Sender).Caption := ' + TLabel(Sender).Caption);
if (TLabel(Sender).Caption = 'Add') then
begin
tempBoolean := false;
for i := 0 to frm.ComponentCount - 1 do
if (frm.Components[i].Top >= 160) and (frm.Components[i].Caption = tempPlugin) then
tempBoolean := true;
exist := false;
FileByName(tempPlugin, exist);
if not tempBoolean and exist then
begin
// Expand form
frm.Height := frm.Height + 36;
// Shift existing components down
TShift(160, 36, frm, false);
// Remove Button
btnRemove := TButton.Create(frm);
btnRemove.Parent := frm;
btnRemove.Caption := 'Remove';
btnRemove.Left := 70;
btnRemove.Top := 160;
btnRemove.Width := 100;
btnRemove.OnClick := Btn_AddOrRemove_OnClick;
// Remove Plugin label
lblPlugin := TLabel.Create(frm);
lblPlugin.Parent := frm;
lblPlugin.Height := 24;
lblPlugin.Top := btnRemove.Top + 2;
lblPlugin.Left := 205;
lblPlugin.Caption := tempPlugin;
end;
slGlobal.Add(tempPlugin);
end
else
if (TLabel(Sender).Caption = 'Remove') then
begin
slGlobal.Delete(slGlobal.IndexOf(ComponentByTop(Sender.Top + 2, frm).Caption));
ComponentByTop(Sender.Top + 2, frm).Free;
Sender.Visible := false;
// Shift existing components up
TShift(Sender.Top, 36, frm, true);
// Shrink form
frm.Height := frm.Height - 36;
end;
end;
procedure GEV_Btn_Remove(Sender: TObject);
var
lblRemovePlugin, lblDetectedFileText, lblDetectedFile: TLabel;
btnAdd, btnOk, btnCancel, btnRemove : TButton;
ddRemovePlugin : TComboBox;
slTemp : TStringList;
GEVfile, TF : IInterface;
frm_Remove : TForm;
debugMsg, exist : boolean;
GEVplugin : string;
i : integer;
begin
// Begin debugMsg section
debugMsg := false;
// Initialize
slTemp := TStringList.Create;
GEVplugin := ComponentByTop(ComponentByCaption('Output Plugin: ', Sender.Parent).Top - 2, Sender.Parent).Caption;
if not StrEndsWith(GEVplugin, '.esl') then
AppendIfMissing(GEVplugin, '.esp');
TF := FileByName(GEVplugin, exist);
if exist then
begin
GEVfile := TF;
end else begin
addMessage('[' + GetElementEditValues(selectedRecord) + '] ' + GEVplugin + ' does not exist; Cannot use ''Remove'' on unspecified plugin');
exit;
end;
// Dialogue Box
frm_Remove := TForm.Create(nil);
while not((frm_Remove.ModalResult = mrCancel) or (frm_Remove.ModalResult = mrOk)) do
begin
frm_Remove := TForm.Create(nil);
try
// Remove all previous TForm components
btnOk := nil;
btnCancel := nil;
// Parent Form; Entire Box
frm_Remove.Width := 850;
frm_Remove.Height := 200;
frm_Remove.Position := poScreenCenter;
frm_Remove.Caption := 'Remove a Specified Master';
// Currently Selected File Label
lblDetectedFileText := TLabel.Create(frm_Remove);
lblDetectedFileText.Parent := frm_Remove;
lblDetectedFileText.Height := 24;
lblDetectedFileText.Top := 68;
lblDetectedFileText.Left := 60;
lblDetectedFileText.Caption := 'Currently Selected File: ';
frm_Remove.Height := frm_Remove.Height + lblDetectedFileText.Height + 12;
// Currently Selected File
lblDetectedFile := TLabel.Create(frm_Remove);
lblDetectedFile.Parent := frm_Remove;
lblDetectedFile.Height := lblDetectedFileText.Height;
lblDetectedFile.Top := lblDetectedFileText.Top;
lblDetectedFile.Left := lblDetectedFileText.Left + (9 * Length(lblDetectedFileText.Caption)) + 85;
lblDetectedFile.Caption := GEVplugin;
// Remove Plugin label
lblRemovePlugin := TLabel.Create(frm_Remove);
lblRemovePlugin.Parent := frm_Remove;
lblRemovePlugin.Height := lblDetectedFileText.Height;
lblRemovePlugin.Top := lblDetectedFileText.Top + lblDetectedFileText.Height + 24;
lblRemovePlugin.Left := lblDetectedFileText.Left;
lblRemovePlugin.Caption := 'Remove Plugin: ';
frm_Remove.Height := frm_Remove.Height + lblRemovePlugin.Height + 12;
// Remove Plugin Drop Down
ddRemovePlugin := TComboBox.Create(frm_Remove);
ddRemovePlugin.Parent := frm_Remove;
ddRemovePlugin.Height := lblRemovePlugin.Height;
ddRemovePlugin.Top := lblRemovePlugin.Top - 2;
ddRemovePlugin.Left := lblRemovePlugin.Left + (9 * Length(lblRemovePlugin.Caption)) + 36;
ddRemovePlugin.Width := 480;
for i := 0 to Pred(MasterCount(GEVfile)) do
if not(StrEndsWith(GetFileName(MasterByIndex(GEVfile, i)), '.esm') or StrEndsWith(GetFileName(MasterByIndex(GEVfile, i)), '.exe') or slContains(slGlobal, GetFileName(MasterByIndex(GEVfile, i)))) then
ddRemovePlugin.Items.Add(GetFileName(MasterByIndex(GEVfile, i)));
// Add Button
btnAdd := TButton.Create(frm_Remove);
btnAdd.Parent := frm_Remove;
btnAdd.Caption := 'Add';
btnAdd.Left := ddRemovePlugin.Left + ddRemovePlugin.Width + 8;
btnAdd.Top := lblRemovePlugin.Top;
btnAdd.Width := 100;
btnAdd.ModalResult := mrRetry;
btnAdd.OnClick := Btn_AddOrRemove_OnClick;
// Items to be removed
{ Debug } if debugMsg then
msgList('[GEV_Btn_Remove] slGlobal := ', slGlobal, '');
for i := 0 to slGlobal.Count - 1 do
begin
exist := false;
FileByName(slGlobal[i], exist);
if exist then
begin
// Remove Plugin label
lblRemovePlugin := TLabel.Create(frm_Remove);
lblRemovePlugin.Parent := frm_Remove;
lblRemovePlugin.Height := 24;
lblRemovePlugin.Top := slGlobal.Objects[i];
lblRemovePlugin.Left := 188;
lblRemovePlugin.Caption := slGlobal[i];
frm_Remove.Height := frm_Remove.Height + lblRemovePlugin.Height + 12;
// Remove Button
btnRemove := TButton.Create(frm_Remove);
btnRemove.Parent := frm_Remove;
btnRemove.Caption := 'Remove';
btnRemove.Left := 80;
btnRemove.Top := slGlobal.Objects[i];
btnRemove.Width := 100;
btnRemove.ModalResult := mrIgnore;
btnRemove.OnClick := Btn_AddOrRemove_OnClick;
end;
end;
// Ok Button
btnOk := TButton.Create(frm_Remove);
btnOk.Parent := frm_Remove;
btnOk.Caption := 'OK';
btnOk.Left := (frm_Remove.Width div 2) - btnOk.Width - 8;
btnOk.Top := frm_Remove.Height - 80;
btnOk.ModalResult := mrOk;
// Cancel Button
btnCancel := TButton.Create(frm_Remove);
btnCancel.Parent := frm_Remove;
btnCancel.Caption := 'Cancel';
btnCancel.Left := btnOk.Left + btnOk.Width + 16;
btnCancel.Top := btnOk.Top;
btnCancel.ModalResult := mrCancel;
if (frm_Remove.ShowModal = mrOk) then
begin
for i := 0 to slGlobal.Count - 1 do
begin
exist := false;
FileByName(slGlobal[i], exist);
if exist then
begin
slTemp.Add(slGlobal[i]);
end;
end;
for i := 0 to slTemp.Count - 1 do
if (slGlobal.IndexOf(slTemp[i]) >= 0) then
slGlobal.Delete(slGlobal.IndexOf(slTemp[i]));
end;
finally
frm_Remove.Free;
end;
end;
// Finalize
slTemp.Free;
debugMsg := false;
// End debugMsg Section
end;
function Btn_ItemTierLevels_OnClick(Sender: TObject): TStringList;
var
lblTier01, lblTier02, lblTier03, lblTier04, lblTier05, lblTier06: TLabel;
ddTier01, ddTier02, ddTier03, ddTier04, ddTier05, ddTier06 : TComboBox;
debugMsg, tempBoolean : boolean;
btnOk, btnCancel : TButton;
i, tempInteger : integer;
frm : TForm;
tempObject : TObject;
begin
// Get Sender Parameters
frm := Sender.Parent;
if not CaptionExists('Tier 01 appears at level: ', frm) then
begin
Sender.Caption := 'Confirm Tiers';
// Shift Components Down
{ Debug } if debugMsg then
addMessage('[Btn_ItemTierLevels_OnClick] Shift Components Down');
frm.Height := frm.Height + 262;
for i := 0 to frm.ComponentCount - 1 do
begin
tempObject := nil;
if (frm.Components[i].Top > Sender.Top) then
begin
tempObject := frm.Components[i];
tempInteger := tempObject.Top;
if Assigned(tempObject) then
begin
tempObject.Top := tempObject.Top + 262;
end;
end;
end;
// Tier 01 Label
lblTier01 := TLabel.Create(frm);
lblTier01.Parent := frm;
lblTier01.Height := 24;
lblTier01.Top := Sender.Top + Sender.Height + 18;
lblTier01.Left := Sender.Left;
lblTier01.Caption := 'Tier 01 appears at level: ';
// Tier 01 Drop Down
ddTier01 := TComboBox.Create(frm);
ddTier01.Parent := frm;
ddTier01.Height := lblTier01.Height;
ddTier01.Top := lblTier01.Top - 2;
ddTier01.Left := 530;
ddTier01.Width := 80;
if slContains(slGlobal, 'ItemTier01') then
begin
ddTier01.Items.Add(IntToStr(slGlobal.Objects[slGlobal.IndexOf('ItemTier01')]));
end else begin
ddTier01.Items.Add(IntToStr(defaultItemTier01));
end;
ddTier01.ItemIndex := 0;
// Tier 02 Label
lblTier02 := TLabel.Create(frm);
lblTier02.Parent := frm;
lblTier02.Height := lblTier01.Height;
lblTier02.Top := lblTier01.Top + lblTier01.Height + 18;
lblTier02.Left := lblTier01.Left;
lblTier02.Caption := 'Tier 02 appears at level: ';
// Tier 02 Drop Down
ddTier02 := TComboBox.Create(frm);
ddTier02.Parent := frm;
ddTier02.Height := lblTier02.Height;
ddTier02.Top := lblTier02.Top - 2;
ddTier02.Left := ddTier01.Left;
ddTier02.Width := ddTier01.Width;
if slContains(slGlobal, 'ItemTier02') then
begin
ddTier02.Items.Add(IntToStr(slGlobal.Objects[slGlobal.IndexOf('ItemTier02')]));
end else begin
ddTier02.Items.Add(IntToStr(defaultItemTier02));
end;
ddTier02.ItemIndex := 0;
// Tier 03 Label
lblTier03 := TLabel.Create(frm);
lblTier03.Parent := frm;
lblTier03.Height := lblTier02.Height;
lblTier03.Top := lblTier02.Top + lblTier02.Height + 18;
lblTier03.Left := lblTier02.Left;
lblTier03.Caption := 'Tier 03 appears at level: ';
// Tier 03 Drop Down
ddTier03 := TComboBox.Create(frm);
ddTier03.Parent := frm;
ddTier03.Height := lblTier03.Height;
ddTier03.Top := lblTier03.Top - 2;
ddTier03.Left := ddTier01.Left;
ddTier03.Width := ddTier01.Width;
if slContains(slGlobal, 'ItemTier03') then
begin
ddTier03.Items.Add(IntToStr(slGlobal.Objects[slGlobal.IndexOf('ItemTier03')]));
end else begin
ddTier03.Items.Add(IntToStr(defaultItemTier03));
end;
ddTier03.ItemIndex := 0;
// Tier 04 Label
lblTier04 := TLabel.Create(frm);
lblTier04.Parent := frm;
lblTier04.Height := lblTier03.Height;
lblTier04.Top := lblTier03.Top + lblTier03.Height + 18;
lblTier04.Left := lblTier03.Left;
lblTier04.Caption := 'Tier 04 appears at level: ';
// Tier 04 Drop Down
ddTier04 := TComboBox.Create(frm);
ddTier04.Parent := frm;
ddTier04.Height := lblTier04.Height;
ddTier04.Top := lblTier04.Top - 2;
ddTier04.Left := ddTier01.Left;
ddTier04.Width := ddTier01.Width;
if slContains(slGlobal, 'ItemTier04') then
begin
ddTier04.Items.Add(IntToStr(slGlobal.Objects[slGlobal.IndexOf('ItemTier04')]));
end else begin
ddTier04.Items.Add(IntToStr(defaultItemTier04));
end;
ddTier04.ItemIndex := 0;
// Tier 05 Label
lblTier05 := TLabel.Create(frm);
lblTier05.Parent := frm;
lblTier05.Height := lblTier04.Height;
lblTier05.Top := lblTier04.Top + lblTier04.Height + 18;
lblTier05.Left := lblTier04.Left;
lblTier05.Caption := 'Tier 05 appears at level: ';
// Tier 05 Drop Down
ddTier05 := TComboBox.Create(frm);
ddTier05.Parent := frm;
ddTier05.Height := lblTier05.Height;
ddTier05.Top := lblTier05.Top - 2;
ddTier05.Left := ddTier01.Left;
ddTier05.Width := ddTier01.Width;
if slContains(slGlobal, 'ItemTier05') then
begin
ddTier05.Items.Add(IntToStr(slGlobal.Objects[slGlobal.IndexOf('ItemTier05')]));
end else begin
ddTier05.Items.Add(IntToStr(defaultItemTier05));
end;
ddTier05.ItemIndex := 0;
// Tier 06 Label
lblTier06 := TLabel.Create(frm);
lblTier06.Parent := frm;
lblTier06.Height := lblTier05.Height;
lblTier06.Top := lblTier05.Top + lblTier05.Height + 18;
lblTier06.Left := lblTier05.Left;
lblTier06.Caption := 'Tier 06 appears at level: ';
// Tier 06 Drop Down
ddTier06 := TComboBox.Create(frm);
ddTier06.Parent := frm;
ddTier06.Height := lblTier06.Height;
ddTier06.Top := lblTier06.Top - 2;
ddTier06.Left := ddTier01.Left;
ddTier06.Width := ddTier01.Width;
if slContains(slGlobal, 'ItemTier06') then
begin
ddTier06.Items.Add(IntToStr(slGlobal.Objects[slGlobal.IndexOf('ItemTier06')]));
end else begin
ddTier06.Items.Add(IntToStr(defaultItemTier06));
end;
ddTier06.ItemIndex := 0;
end else begin
Sender.Caption := 'Configure Tiers';
for i := 1 to 6 do
begin
if CaptionExists('Tier 0' + IntToStr(i) + ' appears at level: ', frm) then
begin
tempObject := ComponentByTop(ComponentByCaption('Tier 0' + IntToStr(i) + ' appears at level: ', frm).Top - 2, frm);
if (IntWithinStr(tempObject.Text) > 0) then
begin
if not slContains(slGlobal, 'ItemTier0' + IntToStr(i)) then
begin
slGlobal.addObject('ItemTier0' + IntToStr(i), IntWithinStr(tempObject.Text));
end else begin
slGlobal.Objects[slGlobal.IndexOf('ItemTier0' + IntToStr(i))] := IntWithinStr(tempObject.Text);
end;
end;
end;
tempObject := ComponentByCaption(('Tier 0' + IntToStr(i) + ' appears at level: '), frm);
tempInteger := tempObject.Top;
if Assigned(tempObject) then
tempObject.Free;
tempObject := ComponentByTop(tempInteger - 2, frm);
if Assigned(tempObject) then
tempObject.Free;
end;
// Shift Components Up
{ Debug } if debugMsg then
addMessage('[Btn_ItemTierLevels_OnClick] Shift Components Up');
frm.Height := frm.Height - 262;
for i := 0 to frm.ComponentCount - 1 do
begin
tempObject := nil;
if (frm.Components[i].Top > Sender.Top) then
begin
tempObject := frm.Components[i];
tempInteger := tempObject.Top;
if Assigned(tempObject) then
begin
tempObject.Top := tempObject.Top - 262;
end;
end;
end;
end;
end;
procedure Btn_Temper_OnClick(Sender: TObject);
var
lblTemperLight, lblTemperHeavy: TLabel;
ddTemperLight, ddTemperHeavy : TComboBox;
debugMsg, tempBoolean : boolean;
btnOk, btnCancel : TButton;
i, tempInteger : integer;
slTemp : TStringList;
frm : TForm;
tempObject : TObject;
begin
// Begin debugMsg section
debugMsg := false;
// Initialize
slTemp := TStringList.Create;
// Get Sender Parameters
{ Debug } if debugMsg then
addMessage('[Btn_Temper_OnClick] Sender := ' + Sender.Caption);
frm := Sender.Parent;
slTemp.CommaText := '"# of Ingots - Light/One-Handed: ", "# of Ingots - Heavy/Two-Handed: "';
if not CaptionExists(slTemp[0], frm) then
begin
// Shift Components Down
{ Debug } if debugMsg then
addMessage('[Btn_Temper_OnClick] Shift Components Down');
frm.Height := frm.Height + slTemp.Count * 44;
TShift(Sender.Top + 3, slTemp.Count * 44, frm, false);
Sender.Caption := 'Confirm Temper Recipe';
// Temper Light Label
{ Debug } if debugMsg then
addMessage('[Btn_Temper_OnClick] Temper Light Label');
lblTemperLight := TLabel.Create(frm);
lblTemperLight.Parent := frm;
lblTemperLight.Height := 24;
lblTemperLight.Top := Sender.Top + Sender.Height + 18;
lblTemperLight.Left := Sender.Left;
lblTemperLight.Caption := '# of Ingots - Light/One-Handed: ';
// Temper Light Drop Down
{ Debug } if debugMsg then
addMessage('[Btn_Temper_OnClick] Temper Light Drop Down');
ddTemperLight := TComboBox.Create(frm);
ddTemperLight.Parent := frm;
ddTemperLight.Height := lblTemperLight.Height;
ddTemperLight.Top := lblTemperLight.Top - 2;
ddTemperLight.Left := 450;
ddTemperLight.Width := 80;
if slContains(slGlobal, 'TemperLight') then
begin
ddTemperLight.Items.Add(IntToStr(slGlobal.Objects[slGlobal.IndexOf('TemperLight')]));
end else begin
ddTemperLight.Items.Add(IntToStr(defaultTemperLight));
end;
ddTemperLight.ItemIndex := 0;
// Temper Heavy Label
{ Debug } if debugMsg then
addMessage('[Btn_Temper_OnClick] Temper Heavy Label');
lblTemperHeavy := TLabel.Create(frm);
lblTemperHeavy.Parent := frm;
lblTemperHeavy.Height := lblTemperLight.Height;
lblTemperHeavy.Top := lblTemperLight.Top + lblTemperLight.Height + 18;
lblTemperHeavy.Left := lblTemperLight.Left;
lblTemperHeavy.Caption := '# of Ingots - Heavy/Two-Handed: ';
// Temper Heavy Drop Down
{ Debug } if debugMsg then
addMessage('[Btn_Temper_OnClick] Temper Heavy Drop Down');
ddTemperHeavy := TComboBox.Create(frm);
ddTemperHeavy.Parent := frm;
ddTemperHeavy.Height := lblTemperHeavy.Height;
ddTemperHeavy.Top := lblTemperHeavy.Top - 2;
ddTemperHeavy.Left := ddTemperLight.Left;
ddTemperHeavy.Width := ddTemperLight.Width;
if slContains(slGlobal, 'TemperHeavy') then
begin
ddTemperHeavy.Items.Add(IntToStr(slGlobal.Objects[slGlobal.IndexOf('TemperHeavy')]));
end else begin
ddTemperHeavy.Items.Add(IntToStr(defaultTemperHeavy));
end;
ddTemperHeavy.ItemIndex := 0;
end else begin
Sender.Caption := 'Configure Temper Recipe';
// Set Result
if slContains(slGlobal, 'TemperLight') then
begin
slGlobal.Objects[slGlobal.IndexOf('TemperLight')] := StrToInt(ComponentByTop(ComponentByCaption('# of Ingots - Light/One-Handed: ', frm).Top - 2, frm).Text);
end
else
slGlobal.addObject('TemperLight', StrToInt(ComponentByTop(ComponentByCaption('# of Ingots - Light/One-Handed: ', frm).Top - 2, frm).Text));
if slContains(slGlobal, 'TemperHeavy') then
begin
slGlobal.Objects[slGlobal.IndexOf('TemperHeavy')] := StrToInt(ComponentByTop(ComponentByCaption('# of Ingots - Heavy/Two-Handed: ', frm).Top - 2, frm).Text);
end
else
slGlobal.addObject('TemperHeavy', StrToInt(ComponentByTop(ComponentByCaption('# of Ingots - Heavy/Two-Handed: ', frm).Top - 2, frm).Text));
// Free Components
for i := 0 to slTemp.Count - 1 do
begin
tempObject := ComponentByCaption(slTemp[i], frm);
tempInteger := tempObject.Top - 2;
tempObject.Free;
tempObject := ComponentByTop(tempInteger, frm);
tempObject.Free;
end;
// Shift form
TShift(Sender.Top + 3, slTemp.Count * 44, frm, true);
frm.Height := frm.Height - slTemp.Count * 44;
end;
// Finalize
slTemp.Free;
debugMsg := false;
// End debugMsg section
end;
procedure Btn_Breakdown_OnClick(Sender: TObject);
var
lblEquipped, lblEnchanted, lblDaedric, lblChitin: TLabel;
ckEquipped, ckEnchanted, ckDaedric, ckChitin : TComboBox;
debugMsg, tempBoolean : boolean;
btnOk, btnCancel : TButton;
i, tempInteger : integer;
slTemp : TStringList;
frm : TForm;
tempObject : TObject;
begin
// Begin debugMsg section
debugMsg := false;
// Initialize
slTemp := TStringList.Create;
// Get Sender Parameters
{ Debug } if debugMsg then
addMessage('[Btn_Temper_OnClick] Sender := ' + Sender.Caption);
{ Debug } if debugMsg then
msgList('[Btn_Temper_OnClick] slGlobal := ', slGlobal, '');
frm := Sender.Parent;
if not CaptionExists('Breakdown Equipped: ', frm) then
begin
// Shift Components
{ Debug } if debugMsg then
addMessage('[Btn_Temper_OnClick] Shift Components Down');
frm.Height := frm.Height + 172;
TShift(Sender.Top + 3, 172, frm, false);
Sender.Caption := 'Confirm Breakdown Recipe';
// Breakdown Equipped Label
{ Debug } if debugMsg then
addMessage('[Btn_Temper_OnClick] Breakdown Equipped Label');
lblEquipped := TLabel.Create(frm);
lblEquipped.Parent := frm;
lblEquipped.Height := 24;
lblEquipped.Top := Sender.Top + Sender.Height + 18;
lblEquipped.Left := Sender.Left;
lblEquipped.Caption := 'Breakdown Equipped: ';
// Breakdown Equipped Check Box
{ Debug } if debugMsg then
addMessage('[Btn_Temper_OnClick] Breakdown Equipped Check Box');
ckEquipped := TCheckBox.Create(frm);
ckEquipped.Parent := frm;
ckEquipped.Height := lblEquipped.Height;
ckEquipped.Top := lblEquipped.Top - 2;
ckEquipped.Left := 465;
ckEquipped.Width := 80;
if slContains(slGlobal, 'BreakdownEquipped') then
begin
ckEquipped.Checked := boolean(slGlobal.Objects[slGlobal.IndexOf('BreakdownEquipped')]);
end
else
ckEquipped.Checked := false;
// Breakdown Enchanted Label
{ Debug } if debugMsg then
addMessage('[Btn_Temper_OnClick] Breakdown Enchanted Label');
lblEnchanted := TLabel.Create(frm);
lblEnchanted.Parent := frm;
lblEnchanted.Height := lblEquipped.Height;
lblEnchanted.Top := lblEquipped.Top + lblEquipped.Height + 18;
lblEnchanted.Left := lblEquipped.Left;
lblEnchanted.Caption := 'Breakdown Enchanted: ';
// Breakdown Enchanted Check Box
{ Debug } if debugMsg then
addMessage('[Btn_Temper_OnClick] Breakdown Enchanted Check Box');
ckEnchanted := TCheckBox.Create(frm);
ckEnchanted.Parent := frm;
ckEnchanted.Height := lblEnchanted.Height;
ckEnchanted.Top := lblEnchanted.Top - 2;
ckEnchanted.Left := ckEquipped.Left;
ckEnchanted.Width := ckEquipped.Width;
if slContains(slGlobal, 'BreakdownEnchanted') then
begin
ckEnchanted.Checked := boolean(slGlobal.Objects[slGlobal.IndexOf('BreakdownEnchanted')]);
end
else
ckEnchanted.Checked := false;
// Breakdown Daedric Label
{ Debug } if debugMsg then
addMessage('[Btn_Temper_OnClick] Breakdown Daedric Label');
lblDaedric := TLabel.Create(frm);
lblDaedric.Parent := frm;
lblDaedric.Height := lblEnchanted.Height;
lblDaedric.Top := lblEnchanted.Top + lblEnchanted.Height + 18;
lblDaedric.Left := lblEnchanted.Left;
lblDaedric.Caption := 'Breakdown Daedric: ';
// Breakdown Daedric Check Box
{ Debug } if debugMsg then
addMessage('[Btn_Temper_OnClick] Breakdown Daedric Check Box');
ckDaedric := TCheckBox.Create(frm);
ckDaedric.Parent := frm;
ckDaedric.Height := lblDaedric.Height;
ckDaedric.Top := lblDaedric.Top - 2;
ckDaedric.Left := ckEquipped.Left;
ckDaedric.Width := ckEquipped.Width;
if slContains(slGlobal, 'BreakdownDaedric') then
begin
ckDaedric.Checked := boolean(slGlobal.Objects[slGlobal.IndexOf('BreakdownDaedric')]);
end
else
ckDaedric.Checked := true;
// Breakdown DLC Label
{ Debug } if debugMsg then
addMessage('[Btn_Temper_OnClick] Breakdown DLC Label');
lblChitin := TLabel.Create(frm);
lblChitin.Parent := frm;
lblChitin.Height := lblDaedric.Height;
lblChitin.Top := lblDaedric.Top + lblDaedric.Height + 18;
lblChitin.Left := lblDaedric.Left;
lblChitin.Caption := 'Breakdown DLC: ';
// Breakdown DLC Check Box
{ Debug } if debugMsg then
addMessage('[Btn_Temper_OnClick] Breakdown DLC Check Box');
ckChitin := TCheckBox.Create(frm);
ckChitin.Parent := frm;
ckChitin.Height := lblChitin.Height;
ckChitin.Top := lblChitin.Top - 2;
ckChitin.Left := ckEquipped.Left;
ckChitin.Width := ckEquipped.Width;
if slContains(slGlobal, 'BreakdownDLC') then
begin
ckChitin.Checked := boolean(slGlobal.Objects[slGlobal.IndexOf('BreakdownDLC')]);
end
else
ckChitin.Checked := true;
end else begin
// Set result
tempObject := ComponentByTop(ComponentByCaption('Breakdown Equipped: ', frm).Top - 2, frm);
if slContains(slGlobal, 'BreakdownEquipped') then
begin
slGlobal.Objects[slGlobal.IndexOf('BreakdownEquipped')] := tempObject.Checked;
end
else
slGlobal.addObject('BreakdownEquipped', tempObject.Checked);
tempObject := ComponentByTop(ComponentByCaption('Breakdown Enchanted: ', frm).Top - 2, frm);
if slContains(slGlobal, 'BreakdownEnchanted') then
begin
slGlobal.Objects[slGlobal.IndexOf('BreakdownEnchanted')] := tempObject.Checked;
end
else
slGlobal.addObject('BreakdownEnchanted', tempObject.Checked);
tempObject := ComponentByTop(ComponentByCaption('Breakdown Daedric: ', frm).Top - 2, frm);
if slContains(slGlobal, 'BreakdownDaedric') then
begin
slGlobal.Objects[slGlobal.IndexOf('BreakdownDaedric')] := tempObject.Checked;
end
else
slGlobal.addObject('BreakdownDaedric', tempObject.Checked);
tempObject := ComponentByTop(ComponentByCaption('Breakdown DLC: ', frm).Top - 2, frm);
if slContains(slGlobal, 'BreakdownDLC') then
begin
slGlobal.Objects[slGlobal.IndexOf('BreakdownDLC')] := tempObject.Checked;
end
else
slGlobal.addObject('BreakdownDLC', tempObject.Checked);
{ Debug } if debugMsg then
msgList('[Btn_Temper_OnClick] slGlobal := ', slGlobal, '');
// Free Components
slTemp.CommaText := '"Breakdown Equipped: ", "Breakdown Enchanted: ", "Breakdown DLC: ", "Breakdown Daedric: ';
for i := 0 to slTemp.Count - 1 do
begin
tempObject := ComponentByCaption(slTemp[i], frm);
tempInteger := tempObject.Top - 2;
tempObject.Free;
tempObject := ComponentByTop(tempInteger, frm);
tempObject.Free;
end;
// Shift form
Sender.Caption := 'Configure Breakdown Recipe';
TShift(Sender.Top + 3, 172, frm, true);
frm.Height := frm.Height - 172;
end;
// Finalize
slTemp.Free;
debugMsg := false;
// End debugMsg section
end;
procedure Btn_Crafting_OnClick(Sender: TObject);
var
lblScaling : TLabel;
ckScaling : TComboBox;
debugMsg, tempBoolean: boolean;
btnOk, btnCancel : TButton;
i, tempInteger : integer;
slTemp : TStringList;
frm : TForm;
tempObject : TObject;
begin
// Begin debugMsg section
debugMsg := false;
// Initialize
slTemp := TStringList.Create;
// Get Sender Parameters
{ Debug } if debugMsg then
addMessage('[Btn_Temper_OnClick] Sender := ' + Sender.Caption);
frm := Sender.Parent;
if not CaptionExists('Recipe Scaling: ', frm) then
begin
// Shift Components
{ Debug } if debugMsg then
addMessage('[Btn_Temper_OnClick] Shift Components Down');
frm.Height := frm.Height + 44;
TShift(Sender.Top + 3, 44, frm, false);
Sender.Caption := 'Confirm Crafting Recipe';
// Enable Scaling Label
{ Debug } if debugMsg then
addMessage('[Btn_Temper_OnClick] Enable Scaling Label');
lblScaling := TLabel.Create(frm);
lblScaling.Parent := frm;
lblScaling.Height := 24;
lblScaling.Top := Sender.Top + 40;
lblScaling.Left := Sender.Left;
lblScaling.Caption := 'Recipe Scaling: ';
// Enable Scaling
{ Debug } if debugMsg then
addMessage('[Btn_Temper_OnClick] Enable Scaling Check Box');
ckScaling := TCheckBox.Create(frm);
ckScaling.Parent := frm;
ckScaling.Height := lblScaling.Height;
ckScaling.Top := lblScaling.Top - 2;
ckScaling.Left := 465;
ckScaling.Width := 80;
if StrWithinSL('RecipeScaling', slGlobal) then
begin
for i := 0 to slGlobal.Count - 1 do
if ContainsText(slGlobal[i], 'RecipeScaling') then
ckScaling.Checked := StrToBool(StrPosCopy(slGlobal[i], '=', false));
end
else
ckScaling.Checked := true;
end else begin
Sender.Caption := 'Configure Crafting Recipe';
// Set Result
tempObject := ComponentByTop(ComponentByCaption('Recipe Scaling: ', frm).Top - 2, frm);
if StrWithinSL('RecipeScaling', slGlobal) then
begin
for i := 0 to slGlobal.Count - 1 do
begin
if ContainsText(slGlobal[i], 'RecipeScaling') then
begin
slGlobal[i] := 'RecipeScaling=' + BoolToStr(tempObject.Checked);
break;
end;
end;
end
else
slGlobal.Add('RecipeScaling=' + BoolToStr(tempObject.Checked));
// Free Components
slTemp.CommaText := '"Recipe Scaling: "';
for i := 0 to slTemp.Count - 1 do
begin
tempObject := ComponentByCaption(slTemp[i], frm);
tempInteger := tempObject.Top - 2;
tempObject.Free;
tempObject := ComponentByTop(tempInteger, frm);
tempObject.Free;
end;
// Shift form
TShift(Sender.Top + 3, 44, frm, true);
frm.Height := frm.Height - 44;
end;
// Finalize
slTemp.Free;
debugMsg := false;
// End debugMsg section
end;
procedure ELLR_Btn_Patch(Sender: TObject);
var
tempFile, tempRecord, tempelement, TF, TFA, TFB : IInterface;
lbl_FileA_Add, lbl_FileA_From, lbl_FileB_To : TLabel;
dd_Patch, dd_FileA, dd_FileA_Plugin, dd_FileB_Plugin: TComboBox;
btnOk, btnCancel : TButton;
slTemp : TStringList;
debugMsg,existA,existB : boolean;
i, x : integer;
frm : TForm;
begin
// Begin debugMsg section
debugMsg := false;
// Initialize
slTemp := TStringList.Create;
// Dialogue Box
frm := TForm.Create(nil);
try
// Parent Form
frm.Width := 1680;
frm.Height := 200;
frm.Position := poScreenCenter;
frm.Caption := 'Patch Two Specific Files';
// File A add caption
lbl_FileA_Add := TLabel.Create(frm);
lbl_FileA_Add.Parent := frm;
lbl_FileA_Add.Height := 24;
lbl_FileA_Add.Top := 68;
lbl_FileA_Add.Left := 60;
lbl_FileA_Add.Caption := 'Add';
// Items or Enchantments Drop Down
dd_FileA := TComboBox.Create(frm);
dd_FileA.Parent := frm;
dd_FileA.Height := 24;
dd_FileA.Top := lbl_FileA_Add.Top - 2;
dd_FileA.Left := lbl_FileA_Add.Left + (10 * Length(lbl_FileA_Add.Caption)) + 20;
dd_FileA.Width := 180;
dd_FileA.Items.Add('Items');
dd_FileA.Items.Add('Enchantments');
dd_FileA.ItemIndex := 0;
dd_FileA.OnClick := ELLR_OnClick_Patch_ddFileA;
// File A from caption
lbl_FileA_From := TLabel.Create(frm);
lbl_FileA_From.Parent := frm;
lbl_FileA_From.Height := 24;
lbl_FileA_From.Top := lbl_FileA_Add.Top;
lbl_FileA_From.Left := dd_FileA.Left + dd_FileA.Width + 8;
lbl_FileA_From.Caption := 'from: ';
// FileA Plugin Drop Down
dd_FileA_Plugin := TComboBox.Create(frm);
dd_FileA_Plugin.Parent := frm;
dd_FileA_Plugin.Height := 24;
dd_FileA_Plugin.Top := lbl_FileA_Add.Top - 2;
dd_FileA_Plugin.Left := lbl_FileA_From.Left + (10 * Length(lbl_FileA_From.Caption));
dd_FileA_Plugin.Width := 500;
for i := 0 to Pred(FileCount) do
dd_FileA_Plugin.Items.Add(GetFileName(FileByIndex(i)));
dd_FileA_Plugin.AutoComplete := true;
dd_FileA_Plugin.Sorted := true;
// File B Variable Label
lbl_FileB_To := TLabel.Create(frm);
lbl_FileB_To.Parent := frm;
lbl_FileB_To.Height := 24;
lbl_FileB_To.Top := dd_FileA.Top + 1;
lbl_FileB_To.Left := dd_FileA_Plugin.Left + dd_FileA_Plugin.Width + 8;
lbl_FileB_To.Caption := 'to Leveled Lists from: ';
// File B Plugin Drop Down
dd_FileB_Plugin := TComboBox.Create(frm);
dd_FileB_Plugin.Parent := frm;
dd_FileB_Plugin.Height := 24;
dd_FileB_Plugin.Top := dd_FileA.Top - 1;
dd_FileB_Plugin.Left := lbl_FileB_To.Left + (10 * Length(lbl_FileB_To.Caption) - 20);
dd_FileB_Plugin.Width := dd_FileA_Plugin.Width;
for i := 0 to Pred(FileCount) do
dd_FileB_Plugin.Items.Add(GetFileName(FileByIndex(i)));
dd_FileB_Plugin.AutoComplete := true;
dd_FileB_Plugin.Sorted := true;
// Ok Button
btnOk := TButton.Create(frm);
btnOk.Parent := frm;
btnOk.Caption := 'Ok';
btnOk.Left := (frm.Width div 2) - btnOk.Width - 8;
btnOk.Top := frm.Height - 80;
btnOk.ModalResult := mrOk;
// Cancel Button
btnCancel := TButton.Create(frm);
btnCancel.Parent := frm;
btnCancel.Caption := 'Cancel';
btnCancel.Left := btnOk.Left + btnOk.Width + 16;
btnCancel.Top := btnOk.Top;
btnCancel.ModalResult := mrCancel;
frm.ShowModal;
if (frm.ModalResult = mrOk) then
begin
existA := false;
existB := false;
TFA := FileByName(dd_FileA_Plugin.Text, existA);
TFB := FileByName(dd_FileB_Plugin.Text, existB);
if existA and existB then
begin
// Sender.Parent.Visible := False;
slGlobal.clear;
existA := false;
TF := FileByName('Patch_' + dd_FileA_Plugin.Text + '_' + dd_FileB_Plugin.Text, existA);
if not existA then
begin
SetObject('ALLAfile', AddNewFileName('Patch_' + dd_FileA_Plugin.Text + '_' + dd_FileB_Plugin.Text), slGlobal);
end
else
SetObject('ALLAfile', TF, slGlobal);
{ Debug } if debugMsg then
addMessage('[ELLR_Btn_Patch] ALLAfile := ' + GetFileName(ObjectToElement(GetObject('ALLAfile', slGlobal))));
SetObject('Patch', TFB, slGlobal);
slTemp.CommaText := 'AMMO, ARMO, WEAP';
for i := 0 to slTemp.Count - 1 do
begin
tempelement := GroupBySignature(TFA, slTemp[i]);
for x := 0 to Pred(ElementCount(tempelement)) do
begin
tempRecord := elementbyindex(tempelement, x);
if not(Length(EditorID(tempRecord)) > 0) then
Continue SetObject(EditorID(tempRecord) + 'Original', tempRecord, slGlobal);
SetObject(EditorID(tempRecord) + 'Template', GetTemplate(tempRecord), slGlobal);
end;
end;
end;
{ Debug } if debugMsg then
msgList('[ELLR_Btn_Patch] slGlobal := ', slGlobal, '');
Sender.Parent.ModalResult := mrRetry;
end;
finally
frm.Free;
end;
// Finalize
slTemp.Free;
debugMsg := false;
// End debugMsg section
end;
procedure GEV_GeneralSettings;
var
lblpercent, lblEnchantmentMultiplier, lblEnchantmentPercent, lblAllowUnenchanting, lblAddtoLL : TLabel;
lblChance, lblDetectedItem, lblDetectedItemText, lblGEVfile, ckPercent, ckAllowUnenchanting, ckAddtoLL: TCheckBox;
btnOk, btnCancel, btnAdvanced, btnRemove, btnItemTierLevels, btnBulk, btnPatch : TButton;
ddChance, ddEnchantmentMultiplier, ddGEVfile, ddAddtoLL : TComboBox;
debugMsg, tempBoolean : boolean;
frm : TForm;
i : integer;
begin
// Begin debugMsg Section
debugMsg := false;
// Initialize Local
if not Assigned(slGlobal) then
slGlobal := TStringList.Create;
frm := TForm.Create(nil);
try
// Parent Form; Entire Box
frm.Width := 650;
frm.Height := 180;
frm.Position := poScreenCenter;
frm.Caption := 'Generate Enchanted Versions Settings';
// Currently Selected Item Label
lblDetectedItemText := TLabel.Create(frm);
lblDetectedItemText.Parent := frm;
lblDetectedItemText.Height := 24;
lblDetectedItemText.Top := 80;
lblDetectedItemText.Left := 60;
lblDetectedItemText.Caption := 'Currently Selected Item: ';
frm.Height := frm.Height + lblDetectedItemText.Height + 18;
// Currently Selected Item
lblDetectedItem := TLabel.Create(frm);
lblDetectedItem.Parent := frm;
lblDetectedItem.Height := lblDetectedItemText.Height;
lblDetectedItem.Top := lblDetectedItemText.Top;
lblDetectedItem.Left := lblDetectedItemText.Left + (10 * Length(lblDetectedItemText.Caption));
lblDetectedItem.Caption := GetElementEditValues(selectedRecord);
// Output Plugin Label
lblGEVfile := TLabel.Create(frm);
lblGEVfile.Parent := frm;
lblGEVfile.Height := lblDetectedItemText.Height;
lblGEVfile.Top := lblDetectedItemText.Top + lblDetectedItemText.Height + 18;
lblGEVfile.Left := lblDetectedItemText.Left;
lblGEVfile.Caption := 'Output Plugin: ';
frm.Height := frm.Height + lblGEVfile.Height + 18;
// Output Plugin Edit Box
ddGEVfile := TComboBox.Create(frm);
ddGEVfile.Parent := frm;
ddGEVfile.Height := lblDetectedItemText.Height;
ddGEVfile.Top := lblGEVfile.Top - 2;
ddGEVfile.Left := lblGEVfile.Left + (9 * Length(lblGEVfile.Caption)) + 36;
ddGEVfile.Width := 280;
if slContains(slGlobal, 'GEVfile') then
ddGEVfile.Items.Add(GetFileName(ObjectToElement(GetObject('GEVfile', slGlobal))))
else
ddGEVfile.Items.Add(defaultOutputPlugin);
ddGEVfile.ItemIndex := 0;
// Item Tier Levels
btnItemTierLevels := TButton.Create(frm);
btnItemTierLevels.Parent := frm;
btnItemTierLevels.Top := lblGEVfile.Top + lblGEVfile.Height + 18;
btnItemTierLevels.Height := 24;
btnItemTierLevels.Left := lblGEVfile.Left + 10 * Length(btnItemTierLevels.Caption);
btnItemTierLevels.Caption := 'Configure Tiers';
btnItemTierLevels.Width := 450;
frm.Height := frm.Height + btnItemTierLevels.Height + 18;
btnItemTierLevels.OnClick := Btn_ItemTierLevels_OnClick;
// Replace in Leveled List Label
lblAddtoLL := TLabel.Create(frm);
lblAddtoLL.Parent := frm;
lblAddtoLL.Height := lblDetectedItemText.Height;
lblAddtoLL.Top := btnItemTierLevels.Top + btnItemTierLevels.Height + 18;;
lblAddtoLL.Left := lblGEVfile.Left;
lblAddtoLL.Caption := 'Replace in Leveled Lists: ';
frm.Height := frm.Height + lblAddtoLL.Height + 18;
// Replace in Leveled List Check Box
ckAddtoLL := TCheckBox.Create(frm);
ckAddtoLL.Parent := frm;
ckAddtoLL.Height := lblAddtoLL.Height;
ckAddtoLL.Left := 485;
ckAddtoLL.Top := lblAddtoLL.Top;
if slContains(slGlobal, 'ReplaceInLeveledList') then
ckAddtoLL.Checked := boolean(GetObject('ReplaceInLeveledList', slGlobal))
else
ckAddtoLL.Checked := true;
// Allow Unenchanting Label
lblAllowUnenchanting := TLabel.Create(frm);
lblAllowUnenchanting.Parent := frm;
lblAllowUnenchanting.Height := 24;
lblAllowUnenchanting.Top := lblAddtoLL.Top + lblAddtoLL.Height + 18;
lblAllowUnenchanting.Left := lblGEVfile.Left;
lblAllowUnenchanting.Caption := 'Allow Unenchanting: ';
frm.Height := frm.Height + lblAllowUnenchanting.Height + 18;
// Allow Unenchanting Check Box
ckAllowUnenchanting := TCheckBox.Create(frm);
ckAllowUnenchanting.Parent := frm;
ckAllowUnenchanting.Height := 24;
ckAllowUnenchanting.Top := lblAllowUnenchanting.Top;
ckAllowUnenchanting.Left := ckAddtoLL.Left;
if slContains(slGlobal, 'AllowDisenchanting') then
ckAllowUnenchanting.Checked := boolean(GetObject('AllowDisenchanting', slGlobal))
else
ckAllowUnenchanting.Checked := true;
// Percent Chance Label
lblChance := TLabel.Create(frm);
lblChance.Parent := frm;
lblChance.Left := lblGEVfile.Left;
lblChance.Top := lblAllowUnenchanting.Top + lblAllowUnenchanting.Height + 18;
lblChance.Caption := 'Use Percent Chance: ';
frm.Height := frm.Height + lblChance.Height + 8;
// Percent Chance Check Box
ckPercent := TCheckBox.Create(frm);
ckPercent.Parent := frm;
ckPercent.Height := lblGEVfile.Height;
ckPercent.Left := ckAddtoLL.Left;
ckPercent.Top := lblChance.Top;
if slContains(slGlobal, 'ChanceBoolean') then
ckPercent.Checked := boolean(GetObject('ChanceBoolean', slGlobal))
else
ckPercent.Checked := true;
// Generate Enchanted Versions % Chance Label
lblpercent := TLabel.Create(frm);
lblpercent.Parent := frm;
lblpercent.Height := ddGEVfile.Height;
lblpercent.Left := ckPercent.Left + 20;
lblpercent.Top := lblChance.Top;
lblpercent.Caption := '%';
// Generate Enchanted Versions % Chance Edit Box
ddChance := TComboBox.Create(frm);
ddChance.Parent := frm;
ddChance.Height := lblpercent.Height;
ddChance.Left := lblpercent.Left + 25;
ddChance.Top := lblChance.Top - 3;
ddChance.Width := 80;
if slContains(slGlobal, 'ChanceMultiplier') then
ddChance.Items.Add(IntToStr(integer(slGlobal.Objects[slGlobal.IndexOf('ChanceMultiplier')])))
else
ddChance.Items.Add('10');
ddChance.ItemIndex := 0;
// Enchantment Multiplier Label
lblEnchantmentMultiplier := TLabel.Create(frm);
lblEnchantmentMultiplier.Parent := frm;
lblEnchantmentMultiplier.Left := lblGEVfile.Left;
lblEnchantmentMultiplier.Top := lblChance.Top + lblChance.Height + 18;
lblEnchantmentMultiplier.Caption := 'Enchantment Strength: ';
frm.Height := frm.Height + lblEnchantmentMultiplier.Height + 18;
// Enchantment Multiplier Edit Box
ddEnchantmentMultiplier := TComboBox.Create(frm);
ddEnchantmentMultiplier.Parent := frm;
ddEnchantmentMultiplier.Height := lblEnchantmentMultiplier.Height;
ddEnchantmentMultiplier.Left := ddChance.Left;
ddEnchantmentMultiplier.Top := lblEnchantmentMultiplier.Top - 1;
ddEnchantmentMultiplier.Width := ddChance.Width;
if slContains(slGlobal, 'EnchMultiplier') then
ddEnchantmentMultiplier.Items.Add(IntToStr(integer(slGlobal.Objects[slGlobal.IndexOf('EnchMultiplier')])))
else
ddEnchantmentMultiplier.Items.Add('100');
ddChance.ItemIndex := 0;
ddEnchantmentMultiplier.ItemIndex := 0;
// Generate Enchanted Versions % Chance Label
lblEnchantmentPercent := TLabel.Create(frm);
lblEnchantmentPercent.Parent := frm;
lblEnchantmentPercent.Height := ddEnchantmentMultiplier.Height;
lblEnchantmentPercent.Left := lblpercent.Left;
lblEnchantmentPercent.Top := ddEnchantmentMultiplier.Top + 4;
lblEnchantmentPercent.Caption := '%';
if StrWithinSL('NoButtons', slGlobal) then
begin
frm.Height := frm.Height - 50;
TShift(0, 50, frm, true);
end else begin
// Remove Button
btnRemove := TButton.Create(frm);
btnRemove.Parent := frm;
btnRemove.Caption := 'Remove';
btnRemove.Left := lblGEVfile.Left;
btnRemove.Top := 20;
btnRemove.Width := 100;
btnRemove.OnClick := GEV_Btn_Remove;
// Patch Button
btnPatch := TButton.Create(frm);
btnPatch.Parent := frm;
btnPatch.Caption := 'Patch';
btnPatch.Left := 285;
btnPatch.Top := 20;
btnPatch.Width := 100;
btnPatch.OnClick := ELLR_Btn_Patch;
// Bulk Button
btnBulk := TButton.Create(frm);
btnBulk.Parent := frm;
btnBulk.Caption := 'Bulk';
btnBulk.Left := frm.Width - 150;
btnBulk.Top := 20;
btnBulk.Width := 100;
btnBulk.OnClick := Btn_Bulk_OnClick;
end;
// Ok Button
btnOk := TButton.Create(frm);
btnOk.Parent := frm;
btnOk.Caption := 'Ok';
btnOk.ModalResult := mrOk;
btnOk.Left := (frm.Width div 2) - btnOk.Width - 8;
btnOk.Top := frm.Height - 80;
// Cancel Button
btnCancel := TButton.Create(frm);
btnCancel.Parent := frm;
btnCancel.Caption := 'Cancel';
btnCancel.ModalResult := mrCancel;
btnCancel.Left := btnOk.Left + btnOk.Width + 16;
btnCancel.Top := btnOk.Top;
// What happens when Ok is pressed
frm.ShowModal;
if (frm.ModalResult = mrOk) then
begin
if not StrEndsWith(ddGEVfile.Caption, '.esl') then
AppendIfMissing(ddGEVfile.Caption, '.esp');
SetObject('CancelAll', false, slGlobal);
{ Debug } if debugMsg then
addMessage('[GEV_GeneralSettings] CancelAll := ' + BoolToStr(boolean(GetObject('CancelAll', slGlobal))));
SetObject('GEVfile', FileByName(ddGEVfile.Caption), slGlobal);
{ Debug } if debugMsg then
addMessage('[GEV_GeneralSettings] GEVfile := ' + GetFileName(ObjectToElement(GetObject('GEVfile', slGlobal))));
SetObject('ChanceBoolean', ckPercent.Checked, slGlobal);
{ Debug } if debugMsg then
addMessage('[GEV_GeneralSettings] ChanceBoolean := ' + BoolToStr(boolean(GetObject('ChanceBoolean', slGlobal))));
SetObject('ReplaceInLeveledList', ckAddtoLL.Checked, slGlobal);
{ Debug } if debugMsg then
addMessage('[GEV_GeneralSettings] ReplaceInLeveledList := ' + BoolToStr(boolean(GetObject('ReplaceInLeveledList', slGlobal))));
SetObject('ChanceMultiplier', StrToInt(ddChance.Text), slGlobal);
{ Debug } if debugMsg then
addMessage('[GEV_GeneralSettings] ChanceMultiplier := ' + IntToStr(integer(GetObject('ChanceMultiplier', slGlobal))));
SetObject('AllowDisenchanting', ckAllowUnenchanting.Checked, slGlobal);
{ Debug } if debugMsg then
addMessage('[GEV_GeneralSettings] AllowDisenchanting := ' + BoolToStr(boolean(GetObject('AllowDisenchanting', slGlobal))));
SetObject('EnchMultiplier', StrToInt(ddEnchantmentMultiplier.Text), slGlobal);
{ Debug } if debugMsg then
addMessage('[GEV_GeneralSettings] EnchMultiplier := ' + IntToStr(integer(GetObject('EnchMultiplier', slGlobal))));
end;
finally
frm.Free;
end;
debugMsg := false;
// End debugMsg Section
end;
// Creates an enchanted copy of the item record and returns it [From Generate Enchanted Versions]
function CreateEnchantedVersion(aRecord, aPlugin, objEffect, enchRecord: IInterface; suffix: string; enchAmount: integer; aBoolean: boolean): IInterface;
var
startTime, stopTime: TDateTime;
tempRecord : IInterface;
tempString : string;
debugMsg : boolean;
enchCost : integer;
begin
// Initialize
debugMsg := false;
startTime := Time;
{ Debug } if debugMsg then
addMessage('[CreateEnchantedVersion] Begin');
{ Debug } if debugMsg then
addMessage('[CreateEnchantedVersions] CreateEnchantedVersion(' + EditorID(aRecord) + ', ' + GetFileName(aPlugin) + ', ' + EditorID(objEffect) + ', ' + EditorID(enchRecord) + ', ' + suffix + ', ' + IntToStr(enchAmount) + ' );');
// Create new enchantment if one is not detected
BeginUpdate(enchRecord);
try
{ Debug } if debugMsg then
addMessage('[CreateEnchantedVersions] SetElementEditValues(enchRecord, EditorID, ' + EditorID(aRecord) + '_' + EditorID(objEffect) + ' );');
SetElementEditValues(enchRecord, 'EDID', EditorID(aRecord) + '_' + EditorID(objEffect));
SetElementEditValues(enchRecord, 'EITM', GetEditValue(objEffect));
if (enchAmount = 0) then
enchAmount := 1;
SetElementEditValues(enchRecord, 'EAMT', enchAmount);
SetElementEditValues(enchRecord, 'FULL', GetElementEditValues(aRecord) + ' of ' + Trim(suffix));
// Set template so that enchanted version will use base record's COBJ
if (Signature(aRecord) = 'WEAP') then
begin
{ Debug } if debugMsg then
addMessage('[CreateEnchantedVersions] SetElementEditValues(' + EditorID(enchRecord) + ', CNAM, ' + ShortName(aRecord) + ' );');
SetElementEditValues(enchRecord, 'CNAM', ShortName(aRecord));
end
else
if (Signature(aRecord) = 'ARMO') then
begin
{ Debug } if debugMsg then
addMessage('[CreateEnchantedVersions] SetElementEditValues(' + EditorID(enchRecord) + ', TNAM, ' + ShortName(aRecord) + ' );');
SetElementEditValues(enchRecord, 'TNAM', ShortName(aRecord));
end;
// Disallow enchanting
if not aBoolean then
begin
if not HasKeyword(enchRecord, 'DisallowEnchanting') then
begin
enchRecord := wbCopyElementToFile(enchRecord, aPlugin, false, true);
SetElementEditValues(enchRecord, 'EDID', EditorID(aRecord) + '_' + EditorID(objEffect) + '_DisallowEnchanting');
AddKeyword(enchRecord, getRecordByFormID('000C27BD'));
end;
end;
finally
EndUpdate(enchRecord);
end;
// Finalize
{ Debug } if debugMsg then
addMessage('[CreateEnchantedVersions] Result := ' + EditorID(enchRecord));
result := enchRecord;
if ProcessTime then
begin
stopTime := Time;
addProcessTime('createEnchantedVersion', TimeBtwn(startTime, stopTime));
end;
end;
// Generates enchanted versions of a list of records from a list of input files
procedure GenerateEnchantedVersionsAuto;
var
slTemp, slItem, slItemTiers, slIndex, slFiles, slTempList, slRecords, slEnchanted, slExistingRecords, slBOD2: TStringList;
tempRecord, tempelement, objEffect, enchLevelList, chanceLevelList, GEVfile, TF : IInterface;
debugMsg, tempBoolean, AllowDisenchanting, ReplaceInLeveledList, exist : boolean;
tempString, suffix, record_sig, Record_edid, PatchFile, enchString : string;
startTime, stopTime, tempStartTime, tempStopTime, processStartTime, processStopTime : TDateTime;
enchAmount, enchMultiplier : Float;
i, x, y, z, tempInteger, enchCount : integer;
begin
// Initialize
debugMsg := false;
startTime := Time;
if not Assigned(slExistingRecords) then
slExistingRecords := TStringList.Create;
if not Assigned(slEnchanted) then
slEnchanted := TStringList.Create;
if not Assigned(slItemTiers) then
slItemTiers := TStringList.Create;
if not Assigned(slTempList) then
slTempList := TStringList.Create;
if not Assigned(slRecords) then
slRecords := TStringList.Create;
if not Assigned(slGlobal) then
slGlobal := TStringList.Create;
if not Assigned(slIndex) then
slIndex := TStringList.Create;
if not Assigned(slFiles) then
slFiles := TStringList.Create;
if not Assigned(slBOD2) then
slBOD2 := TStringList.Create;
if not Assigned(slItem) then
slItem := TStringList.Create;
if not Assigned(slTemp) then
slTemp := TStringList.Create;
// Detect loaded plugins
slTemp.CommaText := 'Skyrim.esm, Dawnguard.esm, Hearthfires.esm, Dragonborn.esm, HolyEnchants.esp, LostEnchantments.esp, "More Interesting Loot for Skyrim.esp", "Summermyst - Enchantments of Skyrim.esp", "Wintermyst - Enchantments of Skyrim.esp"';
for i := 0 to slTemp.Count - 1 do begin
exist := false;
TF := FileByName(slTemp[i], exist);
if exist then
slFiles.addObject(Trim(slTemp[i]), TF);
end;
{ Debug } if debugMsg then
msgList('[GenerateEnchantedVersionsAuto] slFiles := ', slFiles, '');
// Skips dlg if external input is present
{ Debug } if debugMsg then
msgList('[GenerateEnchantedVersionsAuto] slGlobal := ', slGlobal, '');
{ Debug } if debugMsg then
addMessage('[GenerateEnchantedVersionsAuto] AllowDisenchanting := ' + BoolToStr(boolean(GetObject('AllowDisenchanting', slGlobal))));
AllowDisenchanting := boolean(GetObject('AllowDisenchanting', slGlobal));
if slContains(slGlobal, 'AddtoLeveledList') then
ReplaceInLeveledList := boolean(GetObject('AddtoLeveledList', slGlobal))
else
ReplaceInLeveledList := boolean(GetObject('ReplaceInLeveledList', slGlobal));
GEVfile := ObjectToElement(GetObject('GEVfile', slGlobal));
enchMultiplier := integer(GetObject('EnchMultiplier', slGlobal));
{ Debug } if debugMsg then
addMessage('[GenerateEnchantedVersionsAuto] enchMultiplier := ' + IntToStr(enchMultiplier));
// Prep File
if not Assigned(GEVfile) then
begin
GEV_GeneralSettings;
GEVfile := ObjectToElement(GetObject('GEVfile', slGlobal));
end;
if Assigned(GEVfile) then
begin
// Create the necessary groups
slTemp.CommaText := 'LVLI, ARMO, WEAP, COBJ, KYWD';
for x := 0 to slTemp.Count - 1 do
if not HasGroup(GEVfile, slTemp[x]) then
Add(GEVfile, slTemp[x], true);
end else begin
addMessage('[ERROR] [GenerateEnchantedVersionsAuto] GEVfile unassigned');
if Assigned(slExistingRecords) then
slExistingRecords.Free;
if Assigned(slEnchanted) then
slEnchanted.Free;
if Assigned(slItemTiers) then
slItemTiers.Free;
if Assigned(slTempList) then
slTempList.Free;
if Assigned(slRecords) then
slRecords.Free;
if Assigned(slIndex) then
slIndex.Free;
if Assigned(slFiles) then
slFiles.Free;
if Assigned(slBOD2) then
slBOD2.Free;
if Assigned(slTemp) then
slTemp.Free;
if Assigned(slItem) then
slItem.Free;
exit;
end;
{ Debug } if debugMsg then
addMessage('[GenerateEnchantedVersionsAuto] AllowDisenchanting := ' + BoolToStr(boolean(GetObject('AllowDisenchanting', slGlobal))));
// Load slRecords with all valid original records
for i := 0 to slGlobal.Count - 1 do
if ContainsText(slGlobal[i], 'Original') then
SetObject(StrPosCopy(slGlobal[i], 'Original', true), slGlobal.Objects[i], slRecords);
{ Debug } if debugMsg then
msgList('slGlobal := ', slGlobal, '');
{ Debug } if debugMsg then
msgList('slRecords := ', slRecords, '');
// Add masters
tempStartTime := Time;
tempStopTime := Time;
if ProcessTime then
addProcessTime('Add Masters', TimeBtwn(tempStartTime, tempStopTime));
// Build indexes of loaded plugins
tempStartTime := Time;
{ Debug } if debugMsg then
addMessage('[GenerateEnchantedVersionsAuto] Build indexes of loaded plugins');
slTemp.clear;
// Get keywords
for x := 0 to slRecords.Count - 1 do
begin
tempRecord := ObjectToElement(slRecords.Objects[x]);
if (Signature(tempRecord) = 'ARMO') then
begin
slItem.clear;
slGetFlagValues(tempRecord, slItem, false);
// Add clothing type to keywords
for y := 0 to slItem.Count - 1 do
begin
if not((slItem[y] = '35') or (slItem[y] = '36') or (slItem[y] = '42')) then
slItem[y] := slItem[y] + '-' + GetElementEditValues(tempRecord, GetElementType(tempRecord) + '\Armor Type');
end;
// This is an index for the BOD2 slots so they don't have to be generated again in 'Process'
if (slItem.Count > 0) then
begin
for y := 0 to slItem.Count - 1 do
tempString := tempString + ' ' + slItem[y];
slBOD2.Add(EditorID(tempRecord) + '-//-' + tempString);
end;
// Non-vanilla armor types prioritize keywords over BOD2
slTempList.CommaText := '30, 32, 33, 37, 39'; // 30 - Head, 32 - Body, 33 - Gauntlers, 37 - Feet, 39 - Shield
for y := 0 to slItem.Count - 1 do
if not StrWithinSL(slItem[y], slTempList) then
if not slContains(slItem, AssociatedBOD2(slItem[y])) then
slItem.Add(AssociatedBOD2(slItem[y]));
for y := 0 to slItem.Count - 1 do
if not slContains(slTemp, slItem[y]) then
slTemp.Add(slItem[y]);
end
else
if not slContains(slTemp, Signature(tempRecord)) then
slTemp.Add(Signature(tempRecord));
slClearEmptyStrings(slTemp);
end;
{ Debug } if debugMsg then
msgList('[GenerateEnchantedVersionsAuto] Keywords (slTemp) := ', slTemp, '');
for x := 0 to slFiles.Count - 1 do
begin
tempInteger := ElementCount(GroupBySignature(ObjectToElement(slFiles.Objects[x]), 'ENCH'));
enchCount := enchCount + tempInteger;
addMessage('Indexing ' + IntToStr(tempInteger) + ' Enchantments in ' + slFiles[x]);
IndexObjEffect(ObjectToElement(slFiles.Objects[x]), slTemp, slIndex);
end;
if debugMsg then
msgList('[GenerateEnchantedVersionsAuto] slIndex := ', slIndex, '');
tempStopTime := Time;
addProcessTime('Create Library of ' + IntToStr(enchCount) + ' Enchantments', TimeBtwn(tempStartTime, tempStopTime));
// Set Item Tiers
for x := 1 to 6 do
SetObject('0' + IntToStr(x), integer(GetObject('ItemTier0' + IntToStr(x), slGlobal)), slItemTiers);
// Get a list of existing records
slExistingRecords.clear;
slTemp.CommaText := 'ARMO, AMMO, WEAP';
for x := 0 to slTemp.Count - 1 do
begin
tempelement := GroupBySignature(GEVfile, slTemp[x]);
for y := 0 to Pred(ElementCount(tempelement)) do
slExistingRecords.Add(EditorID(elementbyindex(tempelement, y)));
end;
// {Debug} if debugMsg then msgList('[GenerateEnchantedVersionsAuto] slExistingRecords := ', slExistingRecords, '');
// Process
processStartTime := Time;
for i := 0 to slRecords.Count - 1 do
begin
// Common function output
{ Debug } if debugMsg then
msgList('[GenerateEnchantedVersionsAuto] slRecords := ', slRecords, '');
selectedRecord := ObjectToElement(slRecords.Objects[i]);
{ Debug } if debugMsg then
addMessage('[GenerateEnchantedVersionsAuto] selectedRecord := ' + EditorID(ObjectToElement(slRecords.Objects[i])));
record_sig := Signature(selectedRecord);
{ Debug } if debugMsg then
addMessage('[GenerateEnchantedVersionsAuto] record_sig := ' + record_sig);
Record_edid := EditorID(selectedRecord);
// Detect Pre-Existing Leveled Lists
if ProcessTime then
tempStartTime := Time;
{ Debug } if debugMsg then
addMessage('[GenerateEnchantedVersionsAuto] Detecting Pre-Existing Leveled Lists');
enchLevelList := nil;
chanceLevelList := nil;
for x := 0 to Pred(ReferencedByCount(selectedRecord)) do
begin
tempRecord := ReferencedByIndex(selectedRecord, x);
if (Signature(tempRecord) = 'LVLI') then
begin
tempString := EditorID(tempRecord);
if ContainsText(tempString, 'Ench') and ContainsText(tempString, '++') then
begin
if ContainsText(tempString, 'Chance') then
begin
if not(GetLoadOrder(GEVfile) = GetLoadOrder(GetFile(tempRecord))) then
chanceLevelList := wbCopyElementToFile(tempRecord, GEVfile, false, true)
else
chanceLevelList := tempRecord;
end else begin
if not(GetLoadOrder(GEVfile) = GetLoadOrder(GetFile(tempRecord))) then
enchLevelList := wbCopyElementToFile(tempRecord, GEVfile, false, true)
else
enchLevelList := tempRecord;
end;
end;
if Assigned(enchLevelList) and Assigned(chanceLevelList) then
break;
end;
end;
if ProcessTime then
begin
tempStopTime := Time;
addProcessTime('[GEV] Detect Pre-Existing Leveled Lists', TimeBtwn(tempStartTime, tempStopTime));
end;
// Create new Leveled Lists if not already present
{ Debug } if debugMsg then
addMessage('[GenerateEnchantedVersionsAuto] Create new Leveled Lists if not already present');
if not Assigned(enchLevelList) then
begin
slTemp.CommaText := '"Calculate from all levels <= player''s level", "Calculate for each item in count"';
{ Debug } if debugMsg then
msgList('createLeveledList(' + GetFileName(GEVfile) + ', LItem' + StrCapFirst(record_sig) + 'Ench' + Record_edid + '++, ', slTemp, ', 0 );');
enchLevelList := createLeveledList(GEVfile, 'LItem' + StrCapFirst(record_sig) + 'Ench' + Record_edid + '++', slTemp, 0);
addToLeveledList(enchLevelList, selectedRecord, 1);
end;
if not Assigned(chanceLevelList) then
begin
{ Debug } if debugMsg then
addMessage('[GenerateEnchantedVersionsAuto] createChanceLeveledList(' + GetFileName(GEVfile) + ', LItem' + StrCapFirst(record_sig) + 'EnchChance' + Record_edid + '++, ' + IntToStr(integer(GetObject('ChanceMultiplier', slGlobal))) + ', ' + Record_edid + ', ' + EditorID(enchLevelList) + ' );');
chanceLevelList := createChanceLeveledList(GEVfile, 'LItem' + StrCapFirst(record_sig) + 'EnchChance' + Record_edid + '++', integer(GetObject('ChanceMultiplier', slGlobal)), selectedRecord, enchLevelList);
slEnchanted.addObject(Record_edid, chanceLevelList);
end;
// Process records using the indexed list
tempStartTime := Time;
addMessage('[' + IntToStr(i + 1) + '/' + IntToStr(slRecords.Count) + '] Processing ' + Record_edid + ' enchanted versions');
{ Debug } if debugMsg then
addMessage('record_sig := ' + record_sig);
// Get BOD2 list from BOD2 index
for x := 0 to slBOD2.Count - 1 do
begin
if (StrPosCopy(slBOD2[x], '-//-', true) = Record_edid) then
begin
slTemp.CommaText := StrPosCopy(slBOD2[x], '-//-', false);
break;
end;
end;
// Use library to add enchantments
for x := 0 to slIndex.Count - 1 do
begin
objEffect := nil;
suffix := StrPosCopy(slIndex[x], '-//-', true);
enchString := StrPosCopy(slIndex[x], '-//-', false);
if (record_sig = 'ARMO') then
begin
{ Debug } if debugMsg then
msgList('[GenerateEnchantedVersionsAuto] slTemp := ', slTemp, '');
if SLWithinStr(enchString, slTemp) then
begin
objEffect := ObjectToElement(slIndex.Objects[x]);
{ Debug } if debugMsg then
addMessage('[GenerateEnchantedVersionsAuto] objEffect := ' + EditorID(objEffect));
end;
end
else
if ContainsText(enchString, record_sig) then
begin
objEffect := ObjectToElement(slIndex.Objects[x]);
{ Debug } if debugMsg then
addMessage('[GenerateEnchantedVersionsAuto] objEffect := ' + EditorID(objEffect));
end;
if Assigned(objEffect) then
begin
tempInteger := GetEnchLevel(objEffect, slItemTiers); { Debug }
if debugMsg then
addMessage('[GenerateEnchantedVersionsAuto] enchLevel := ' + IntToStr(tempInteger));
if (tempInteger > 0) then
begin
{ Debug } if debugMsg then
addMessage('[GenerateEnchantedVersionsAuto] enchAmount := ' + IntToStr((enchMultiplier * GetElementNativeValues(objEffect, 'ENIT\Enchantment Amount')) div 100) + ' * ' + IntToStr(GetElementNativeValues(objEffect, 'ENIT\Enchantment Amount')));
enchAmount := (enchMultiplier * GetEnchAmount(tempInteger)) div 100;
// Pre-Existing records
if not slContains(slExistingRecords, EditorID(selectedRecord) + '_' + EditorID(objEffect)) then
begin
tempelement := wbCopyElementToFile(selectedRecord, GEVfile, true, true); { Debug }
if debugMsg then
addMessage('[GenerateEnchantedVersionsAuto] enchRecord := ' + EditorID(tempelement));
end
else
Continue;
// Generate Enchantment
tempRecord := CreateEnchantedVersion(selectedRecord, GEVfile, objEffect, tempelement, suffix, Round(enchAmount), AllowDisenchanting); { Debug }
if debugMsg then
addMessage('[GenerateEnchantedVersionsAuto] tempRecord := CreateEnchantedVersion(' + Record_edid + ', ' + GetFileName(GEVfile) + ', ' + EditorID(objEffect) + ', ' + EditorID(tempelement) + ', ' + StrPosCopy(GetElementEditValues(objEffect), 'of', false) + ', ' + IntToStr(Round(enchAmount)) + ', ' + BoolToStr(AllowDisenchanting) + ' );');
addToLeveledList(enchLevelList, tempRecord, tempInteger); { Debug }
if debugMsg then
addMessage('[GenerateEnchantedVersionsAuto] AddToLeveledList(' + EditorID(enchLevelList) + ', ' + EditorID(tempRecord) + ', ' + IntToStr(tempInteger) + ' );');
slExistingRecords.Add(EditorID(tempRecord));
end;
end;
end;
// This replaces records in the vanilla leveled lists
if ReplaceInLeveledList then
begin
// Add to enchanted lists
tempelement := nil;
if (Signature(selectedRecord) = 'WEAP') then
begin
tempelement := MainRecordByEditorID(GroupBySignature(FileByName('Skyrim.esm'), 'LVLI'), 'LItemEnch' + EditorID(ObjectToElement(GetObject(EditorID(selectedRecord) + 'Template', slGlobal)))); { Debug }
if debugMsg then
addMessage('[GenerateEnchantedVersionsAuto] tempElement := ' + EditorID(tempelement));
end
else
tempelement := MainRecordByEditorID(GroupBySignature(FileByName('Skyrim.esm'), 'LVLI'), 'LItemEnchArmor' + StrPosCopy(GetElementEditValues(selectedRecord, GetElementType(selectedRecord) + '\Armor Type'), ' ', true) + GetItemType(selectedRecord)); { Debug }
if debugMsg then
addMessage('[GenerateEnchantedVersionsAuto] tempElement := ' + EditorID(tempelement));
if Assigned(tempelement) then
begin
tempRecord := nil;
if HasFileOverride(tempelement, GEVfile) then
begin
tempRecord := GetFileOverride(tempelement, GEVfile);
end
else
tempRecord := wbCopyElementToFile(selectedRecord, GEVfile, false, true);
if Assigned(tempRecord) and Assigned(enchLevelList) then
begin
{ Debug } if debugMsg then
addMessage('[GenerateEnchantedVersionsAuto] if Assigned(tempRecord) and Assigned(enchLevelList) then ReplaceInLeveledListAuto(' + EditorID(tempRecord) + ', ' + EditorID(enchLevelList) + ', ' + GetFileName(GEVfile) + ' );');
ReplaceInLeveledListAuto(tempRecord, enchLevelList, GEVfile);
end;
end;
end;
// Process Time Messages
if ProcessTime then
begin
tempStopTime := Time;
addProcessTime('[GEV] Process Enchanted Versions', TimeBtwn(tempStartTime, tempStopTime));
end;
end;
if ProcessTime then
begin
processStopTime := Time;
addProcessTime('Generate Enchantments for ' + IntToStr(slRecords.Count) + ' Records', TimeBtwn(processStartTime, processStopTime));
end;
// Replace original with enchanted versions
if ReplaceInLeveledList then
ReplaceInLeveledListByList(slRecords, slEnchanted, GEVfile);
// Set Result
{ Debug } if debugMsg then
msgList('[GenerateEnchantedVersionsAuto] slGlobal := ', slGlobal, '');
// Finalize
if ProcessTime then
begin
stopTime := Time;
addProcessTime('GenerateEnchantedVersionsAuto', TimeBtwn(startTime, stopTime));
end;
if Assigned(slExistingRecords) then
slExistingRecords.Free;
if Assigned(slEnchanted) then
slEnchanted.Free;
if Assigned(slItemTiers) then
slItemTiers.Free;
if Assigned(slTempList) then
slTempList.Free;
if Assigned(slRecords) then
slRecords.Free;
if Assigned(slIndex) then
slIndex.Free;
if Assigned(slFiles) then
slFiles.Free;
if Assigned(slBOD2) then
slBOD2.Free;
if Assigned(slTemp) then
slTemp.Free;
if Assigned(slItem) then
slItem.Free;
end;
// Indexes an Object effect
procedure IndexObjEffect(aRecord: IInterface; BOD2List, aList: TStringList);
var
slTemp, slBOD2, slFlagOutput, slEnchantmentSuffix, slTempList: TStringList;
tempString, suffix, sortingSuffix : string;
objEffect, tempRecord : IInterface;
debugMsg, tempBoolean : boolean;
startTime, stopTime : TDateTime;
i, x, y : integer;
begin
// Initialize
debugMsg := false;
startTime := Time;
slEnchantmentSuffix := TStringList.Create;
slFlagOutput := TStringList.Create;
slTempList := TStringList.Create;
slBOD2 := TStringList.Create;
slTemp := TStringList.Create;
{ Debug } if debugMsg then
msgList('[IndexObjEffect] input BOD2 := ', BOD2List, '');
// Function
slTempList.CommaText := '35, 36, 42';
for i := 0 to Pred(ElementCount(GroupBySignature(aRecord, 'ENCH'))) do
begin
// Clear info from previous loops
suffix := nil;
slEnchantmentSuffix.clear;
slBOD2.Assign(BOD2List);
// Skip invalid records
tempRecord := WinningOverride(elementbyindex(GroupBySignature(aRecord, 'ENCH'), i));
if (EditorID(objEffect) = EditorID(tempRecord)) then
Continue;
objEffect := tempRecord; { Debug }
if debugMsg then
addMessage('[IndexObjEffect] objEffect := ' + EditorID(objEffect));
tempBoolean := false;
tempString := EditorID(objEffect);
slTemp.CommaText := 'Nightingale, Chillrend, Frostmere, trap, Miraak, Base, Haknir';
if SLWithinStr(tempString, slTemp) then
Continue;
slTemp.clear;
// Check for recognizable EditorID
// Check for vanilla suffix
for x := 1 to 6 do
if StrEndsWith(tempString, '0' + IntToStr(x)) then
tempBoolean := true;
// Check for Sorting Mod prefix
if not tempBoolean then
if (Copy(tempString, 1, 2) = 'aa') then
tempBoolean := true;
// Check for Eldritch Magic Enchantments Prefix
if not tempBoolean then
if ContainsText(tempString, 'EldEnch') then
tempBoolean := true;
tempString := nil;
if not tempBoolean then
Continue;
// Search objEffect references for matching BOD2 slot
for x := 0 to Pred(ReferencedByCount(objEffect)) do
begin
tempRecord := ReferencedByIndex(objEffect, x);
// Store reference name for suffix determination
if ContainsText(GetElementEditValues(tempRecord), 'of ') then
slEnchantmentSuffix.Add(StrPosCopy(GetElementEditValues(tempRecord), 'of ', false));
if (slBOD2.Count <= 0) then
Continue;
// {Debug} if debugMsg then addMessage('[IndexObjEffect] tempRecord := '+EditorID(tempRecord));
if (Signature(tempRecord) = 'ARMO') then
begin
// Get this record's BOD2
slFlagOutput.clear;
slGetFlagValues(tempRecord, slFlagOutput, false);
if not(slFlagOutput.Count > 0) then
Continue;
// Evaluate BOD2
for y := 0 to slFlagOutput.Count - 1 do
begin
// Add clothing type to BOD2
if not SLWithinStr(slFlagOutput[y], slTempList) then
slFlagOutput[y] := Trim(slFlagOutput[y]) + '-' + Trim(GetElementEditValues(tempRecord, GetElementType(tempRecord) + '\Armor Type'));
// Add to this ObjEffect's BOD2 if not already present
if not slContains(slTemp, slFlagOutput[y]) then
slTemp.Add(slFlagOutput[y]);
end;
end
else
if not slContains(slTemp, Signature(tempRecord)) then
slTemp.Add(Signature(tempRecord));
// If detected BOD2 matches input BOD2 add to this record's list
for y := 0 to slTemp.Count - 1 do
begin
if slContains(slBOD2, slTemp[y]) then
begin
tempString := Trim(tempString + ' ' + slTemp[y]);
slBOD2.Delete(slBOD2.IndexOf(slTemp[y]));
end;
end;
end;
{ Debug } if debugMsg then
addMessage('[IndexObjEffect] ' + EditorID(objEffect) + ' slBOD2 := ' + tempString);
// Create slIndex entry if objEffect has valid slots
if (tempString <> '') then
begin
// Sorting Mod Stuff
// Determine item suffix
suffix := MostCommonString(slEnchantmentSuffix);
// If there is no enchantment name then use the objEffect name
if (suffix = '') then
suffix := StrPosCopy(GetElementEditValues(objEffect), 'of', false);
if (sortingSuffix <> '') then
suffix := suffix + ' ' + DecToRoman(StrToInt(sortingSuffix));
// Make slIndex Entry
{ Debug } if debugMsg then
addMessage('[IndexObjEffect] aList.AddObject(' + Trim(tempString) + ', ' + EditorID(objEffect) + ' );');
aList.addObject(suffix + '-//-' + tempString, objEffect);
end;
end;
// Finalize
{ Debug } if debugMsg then
msgList('[IndexObjEffect] aList := ', aList, '');
stopTime := Time;
if ProcessTime then
addProcessTime('IndexObjEffect', TimeBtwn(startTime, stopTime));
slEnchantmentSuffix.Free;
slFlagOutput.Free;
slTempList.Free;
slBOD2.Free;
slTemp.Free;
end;
// Gets an Enchantment Amount from the level
function GetEnchAmount(aLevel: integer): integer;
var
debugMsg: boolean;
begin
// Initialize
debugMsg := false;
{ Debug } if debugMsg then
addMessage('[GetEnchAmount] GetEnchAmount(' + IntToStr(aLevel) + ' );');
// Process
case aLevel of
1 .. 9:
result := 500;
10 .. 19:
result := 1000;
20 .. 29:
result := 1500;
30 .. 34:
result := 2000;
35 .. 39:
result := 2500;
40 .. 100:
result := 3000;
else
addMessage('[GetEnchAmount] ' + IntToStr(aLevel) + ' not recognized');
end;
{ Debug } if debugMsg then
addMessage('[GetEnchAmount] Result := ' + IntToStr(result));
end;
// Gets an object by IntToStr EditorID
function IndexOfObjectEDID(s: string; aList: TStringList): integer;
var
debugMsg: boolean;
i : integer;
begin
// Begin debugMsg section
debugMsg := false;
{ Debug } if debugMsg then
msgList('[IndexOfObjectEDID] IndexOfObjectEDID ''' + s + ''', (', aList, ');');
result := -1;
for i := 0 to aList.Count - 1 do
begin
if (EditorID(ObjectToElement(aList.Objects[i])) = s) then
begin
result := i;
{ Debug } if debugMsg then
addMessage('[IndexOfObjectEDID] Result := ' + IntToStr(result));
end;
end;
debugMsg := false;
// End debugMsg section
end;
// Gets an object by IntToStr EditorID
function IndexOfObjectbyFULL(s: string; aList: TStringList): integer;
var
debugMsg: boolean;
i : integer;
begin
// Begin debugMsg section
debugMsg := false;
{ Debug } if debugMsg then
addMessage('[IndexOfObjectbyFULL] IndexOfObjectbyFULL(' + s + ', aList );');
for i := 0 to aList.Count - 1 do
begin
if ContainsText(GetElementEditValues(ObjectToElement(aList.Objects[i])), s) then
begin
result := i;
{ Debug } if debugMsg then
addMessage('[IndexOfObjectbyFULL] Result := ' + IntToStr(result));
end;
end;
debugMsg := false;
// End debugMsg section
end;
function IsHighestOverride(aRecord: IInterface; aInteger: integer): boolean;
var
debugMsg: boolean;
begin
// Begin debugMsg section
debugMsg := false;
result := false;
result := IsWinningOVerride(aRecord);
{ Debug } if debugMsg then
addMessage('[IsHighestOverride] IsHighestOverride(' + EditorID(aRecord) + ', ' + GetFileName(FileByLoadOrder(aInteger)) + ' )');
{ Debug } if debugMsg then
addMessage('[IsHighestOverride] if GetLoadOrder(' + GetFileName(GetFile(aRecord)) + ' ) := ' + IntToStr(GetLoadOrder(GetFile(aRecord))) + ' = ' + IntToStr(GetLoadOrder(GetFile(HighestOverrideOrSelf(aRecord, aInteger)))) + ' := GetLoadOrder(' + GetFileName(GetFile(HighestOverrideOrSelf(aRecord, aInteger))) + ' ) then');
if (GetLoadOrder(GetFile(aRecord)) = GetLoadOrder(GetFile(HighestOverrideOrSelf(aRecord, aInteger)))) then
result := true;
{ Debug } if debugMsg then
addMessage('[IsHighestOverride] Result := ' + BoolToStr(result));
debugMsg := false;
// End debugMsg section
end;
// Creates new COBJ record to make item temperable [SkyrimUtils]
function MakeTemperable(aRecord: IInterface; lightInteger, heavyInteger: integer; aPlugin: IInterface): IInterface;
var
recipeTemper, recipeCondition, tempRecord: IInterface;
tempBoolean : boolean;
slTemp : TStringList;
record_sig : string;
debugMsg : boolean;
ki, e, i : integer;
keywords, keyword, ci : IInterface;
begin
// Begin debugMsg section
debugMsg := false;
// Initialize
slTemp := TStringList.Create;
// CHECK FOR PRE-EXISTING
// Common function output
{ Debug } if debugMsg then
addMessage('[MakeTemperable] MakeTemperable(' + EditorID(aRecord) + ', ' + IntToStr(lightInteger) + ', ' + IntToStr(heavyInteger) + ', ' + GetFileName(aPlugin) + ' );');
record_sig := Signature(aRecord);
{ Debug } if debugMsg then
addMessage('[MakeTemperable] record_sig := ' + record_sig);
// Filter invalid records
tempBoolean := false;
if Assigned(ElementByPath(aRecord, 'CNAM')) then
tempBoolean := true;
if not tempBoolean then
if not((record_sig = 'WEAP') or (record_sig = 'ARMO') or (record_sig = 'AMMO')) then
tempBoolean := true;
slTemp.CommaText := 'Circlet, Ring, Necklace';
if not tempBoolean then
if StrWithinSL(GetEditValue(aRecord), slTemp) or StrWithinSL(EditorID(aRecord), slTemp) then
tempBoolean := true;
if not tempBoolean then
for i := 0 to Pred(ReferencedByCount(aRecord)) do
if (Signature(ReferencedByIndex(aRecord, i)) = 'COBJ') and ContainsText(EditorID(ReferencedByIndex(aRecord, i)), 'Temper') then
tempBoolean := true;
if not tempBoolean then
if IsClothing(aRecord) then
tempBoolean := true;
if IsClothing(aRecord) then
tempBoolean := true;
if tempBoolean then
begin
slTemp.Free;
exit;
end;
// Add conditions
{ Debug } if debugMsg then
addMessage('[MakeTemperable] Add conditions');
recipeTemper := FindRecipe(false, HashedTemperList, aRecord, aPlugin);
if Assigned(recipeTemper) then
begin
{ Debug } if debugMsg then
addMessage('Recipe Found for: ' + name(aRecord) + ' emptying');
BeginUpdate(recipeTemper);
try
for e := ElementCount(ElementByPath(recipeTemper, 'Items')) - 1 downto 0 do
begin
RemoveByIndex(ElementByPath(recipeTemper, 'Items'), e, false);
end;
for e := ElementCount(ElementByPath(recipeTemper, 'Conditions')) - 1 downto 0 do
begin
RemoveByIndex(ElementByPath(recipeTemper, 'Conditions'), e, false);
end;
finally
EndUpdate(recipeTemper);
end;
end;
if not Assigned(recipeTemper) then
begin
{ Debug } if debugMsg then
addMessage('No Recipe Found for: ' + name(aRecord) + ' Generating new one');
recipeTemper := createRecord(aPlugin, 'COBJ');
// add reference to the created object
SetElementEditValues(recipeTemper, 'CNAM', name(aRecord));
// set Created Object Count
SetElementEditValues(recipeTemper, 'NAM1', '1');
end;
Add(recipeTemper, 'Conditions', true);
// RemoveInvalidEntries(recipeTemper);
recipeCondition := ElementByPath(recipeTemper, 'Conditions');
BeginUpdate(recipeCondition);
try
SetElementEditValues(ElementByPath(recipeCondition, 'Condition\CTDA'), 'Type', '00010000');
SetElementEditValues(ElementByPath(recipeCondition, 'Condition\CTDA'), 'Comparison Value', '1');
SetElementEditValues(ElementByPath(recipeCondition, 'Condition\CTDA'), 'Function', 'EPTemperingItemIsEnchanted');
SetElementEditValues(ElementByPath(recipeCondition, 'Condition\CTDA'), 'Run On', 'Subject');
SetElementEditValues(ElementByPath(recipeCondition, 'Condition\CTDA'), 'Parameter #3', '-1');
finally
EndUpdate(recipeCondition);
end;
addPerkCondition(ElementByPath(recipeTemper, 'Conditions'), getRecordByFormID('0005218E')); // ArcaneBlacksmith
{ Debug } if debugMsg then
addMessage('[MakeTemperable] if record_sig := ' + record_sig + ' = WEAP then begin');
if (record_sig = 'WEAP') then
begin
SetElementEditValues(recipeTemper, 'BNAM', GetEditValue(getRecordByFormID('00088108')));
{ Debug } if debugMsg then
addMessage('[MakeTemperable] GetFileName(GetFile(aRecord)) := ' + GetFileName(GetFile(aRecord)));
SetElementEditValues(recipeTemper, 'EDID', 'TemperWeapon_' + Trim(RemoveSpaces(RemoveFileSuffix(GetFileName(GetFile(aRecord))))) + '_' + Trim(EditorID(aRecord)));
end;
{ Debug } if debugMsg then
addMessage('[MakeTemperable] if record_sig := ' + record_sig + ' = ARMO then begin');
if (record_sig = 'ARMO') then
begin
SetElementEditValues(recipeTemper, 'BNAM', GetEditValue(getRecordByFormID('000ADB78')));
{ Debug } if debugMsg then
addMessage('[MakeTemperable] GetFileName(GetFile(aRecord)) := ' + GetFileName(GetFile(aRecord)));
SetElementEditValues(recipeTemper, 'EDID', 'TemperArmor_' + Trim(RemoveSpaces(RemoveFileSuffix(GetFileName(GetFile(aRecord))))) + '_' + Trim(EditorID(aRecord)));
end;
// Add valid combinations
slTemp.clear;
// Weapon
slTemp.addObject('WeapMaterialIron', getRecordByFormID('0005ACE4'));
slTemp.addObject('WeapMaterialSteel', getRecordByFormID('0005ACE5'));
slTemp.addObject('WeapMaterialElven', getRecordByFormID('0005ADA0'));
slTemp.addObject('WeapMaterialDwarven', getRecordByFormID('000DB8A2'));
slTemp.addObject('WeapMaterialEbony', getRecordByFormID('0005AD9D'));
slTemp.addObject('WeapMaterialDaedric', getRecordByFormID('0005AD9D'));
slTemp.addObject('WeapMaterialWood', getRecordByFormID('0006F993'));
slTemp.addObject('WeapMaterialSilver', getRecordByFormID('0005ACE3'));
slTemp.addObject('WeapMaterialOrcish', getRecordByFormID('0005AD99'));
slTemp.addObject('WeapMaterialGlass', getRecordByFormID('0005ADA1'));
slTemp.addObject('WeapMaterialFalmer', getRecordByFormID('0003AD57'));
slTemp.addObject('WeapMaterialFalmerHoned', getRecordByFormID('0003AD57'));
slTemp.addObject('DLC1WeapMaterialDragonbone', getRecordByFormID('0003ADA4'));
slTemp.addObject('DLC2WeaponMaterialStalhrim', getRecordByFormID('0402B06B'));
// Armor
slTemp.addObject('ArmorMaterialIron', getRecordByFormID('0005ACE4'));
slTemp.addObject('ArmorMaterialStudded', getRecordByFormID('0005ACE4'));
slTemp.addObject('ArmorMaterialElven', getRecordByFormID('0005AD9F'));
slTemp.addObject('DLC2ArmorMaterialChitinLight', getRecordByFormID('0402B04E'));
slTemp.addObject('DLC2ArmorMaterialChitinHeavy', getRecordByFormID('0402B04E'));
slTemp.addObject('DLC1ArmorMaterielFalmerHeavy', getRecordByFormID('0003AD57'));
slTemp.addObject('DLC1ArmorMaterielFalmerHeavyOriginal', getRecordByFormID('0003AD57'));
slTemp.addObject('DLC1ArmorMaterialFalmerHardened', getRecordByFormID('0402B06B'));
slTemp.addObject('DLC2ArmorMaterialBonemoldLight', getRecordByFormID('0401CD7C'));
slTemp.addObject('DLC2ArmorMaterialBonemoldHeavy', getRecordByFormID('0401CD7C'));
slTemp.addObject('ArmorMaterialScaled', getRecordByFormID('0005AD93'));
slTemp.addObject('ArmorMaterialIronBanded', getRecordByFormID('0005AD93'));
slTemp.addObject('DLC2ArmorMaterialStalhrimLight', getRecordByFormID('0402B06B'));
slTemp.addObject('DLC2ArmorMaterialStalhrimHeavy', getRecordByFormID('0402B06B'));
slTemp.addObject('DLC2ArmorMaterialNordicLight', getRecordByFormID('0005ADA0'));
slTemp.addObject('DLC2ArmorMaterialNordicHeavy', getRecordByFormID('0005ADA0'));
slTemp.addObject('ArmorMaterialElvenGilded', getRecordByFormID('0005ADA0'));
slTemp.addObject('ArmorMaterialHide', getRecordByFormID('000DB5D2'));
slTemp.addObject('ArmorMaterialLeather', getRecordByFormID('000DB5D2'));
slTemp.addObject('DLC2ArmorMaterialMoragTong', getRecordByFormID('000DB5D2'));
slTemp.addObject('ArmorMaterialSilver', getRecordByFormID('0005ACE3'));
slTemp.addObject('ArmorMaterialGlass', getRecordByFormID('0005ADA1'));
slTemp.addObject('ArmorMaterialEbony', getRecordByFormID('0005AD9D'));
slTemp.addObject('ArmorMaterialDaedric', getRecordByFormID('0005AD9D'));
slTemp.addObject('ArmorMaterialDwarven', getRecordByFormID('000DB8A2'));
slTemp.addObject('ArmorMaterialDragonscale', getRecordByFormID('0003ADA3'));
slTemp.addObject('ArmorMaterialDragonplate', getRecordByFormID('0003ADA4'));
slTemp.addObject('ArmorMaterialSteel', getRecordByFormID('0005ACE5'));
slTemp.addObject('ArmorMaterialImperialHeavy', getRecordByFormID('0005ACE5'));
slTemp.addObject('ArmorMaterialImperialLight', getRecordByFormID('0005ACE5'));
slTemp.addObject('ArmorMaterialSteelPlate', getRecordByFormID('0005ACE5'));
slTemp.addObject('ArmorMaterialStormcloak', getRecordByFormID('0005ACE5'));
slTemp.addObject('ArmorMaterialImperialStudded', getRecordByFormID('0005ACE5'));
slTemp.addObject('DLC1ArmorMaterialDawnguard', getRecordByFormID('0005ACE5'));
// Detect value
if slTemp.Count > 0 then
begin
Add(recipeTemper, 'items', true);
for i := 0 to slTemp.Count - 1 do
begin
{ Debug } if debugMsg then
addMessage('[MakeTemperable] if HasKeyword(' + EditorID(aRecord) + ', ' + slTemp[i] + ' ) then begin');
if HasKeyword(aRecord, slTemp[i]) then
begin
{ Debug } if debugMsg then
addMessage('[MakeTemperable] addItem(' + EditorID(recipeTemper) + ', ' + EditorID(ObjectToElement(slTemp.Objects[i])) + ', 1);');
addItem(recipeTemper, ObjectToElement(slTemp.Objects[i]), 1);
end;
end;
end else begin
addMessage('[ERROR] [MakeTemperable] Keyword list did not generate');
// Remove(recipeTemper);
exit;
end;
RemoveInvalidEntries(recipeTemper);
{
// If a vanilla keyword is not detected
if (GetElementEditValues(recipeTemper, 'COCT') = '') then begin
tempRecord := GetTemplate(aRecord);
for i := 0 to slTemp.Count-1 do begin
if debugMsg then addMessage('[MakeTemperable] if HasKeyword('+EditorID(tempRecord)+', '+slTemp[i]+' ) then begin');
if HasKeyword(tempRecord, slTemp[i]) then begin
if debugMsg then addMessage('[MakeTemperable] addItem('+EditorID(recipeTemper)+', '+EditorID(ObjectToElement(slTemp.Objects[i]))+', 1);');
if ElementExists(aRecord, 'BOD2') then begin
if debugMsg then addMessage('[MakeTemperable] if (GetElementEditValues(aRecord, BOD2\Armor Type) := '+GetElementEditValues(aRecord, 'BOD2\Armor Type')+' = Heavy Armor ) then begin');
if (GetElementEditValues(aRecord, 'BOD2\Armor Type') = 'Heavy Armor') then begin
addItem(recipeTemper, ObjectToElement(slTemp.Objects[i]), heavyInteger);
end else if (GetElementEditValues(aRecord, 'BOD2\Armor Type') = 'Light Armor') then
addItem(recipeTemper, ObjectToElement(slTemp.Objects[i]), lightInteger);
end else if ElementExists(aRecord, 'DNAM\Skill') or ElementExists(aRecord, 'DNAM\Animation Type') then begin
if (GetElementEditValues(aRecord, 'DNAM\Skill') = 'Two Handed') or ContainsText(GetElementEditValues(aRecord, 'DNAM\Animation Type'), 'TwoHand') then begin
addItem(recipeTemper, ObjectToElement(slTemp.Objects[i]), heavyInteger);
end else
addItem(recipeTemper, ObjectToElement(slTemp.Objects[i]), lightInteger);
end else
addItem(recipeTemper, ObjectToElement(slTemp.Objects[i]), lightInteger);
end;
end;
end;
}
// above is where an unknown is found something to get it a temper recipe
if GetElementEditValues(recipeTemper, 'COCT') = '' then
begin
{ debug } if debugMsg then
addMessage('[MakeTemperable] there was no vanilla keyword useable for a temper recipe');
keywords := ElementByPath(aRecord, 'KWDA');
for ki := 0 to ElementCount(keywords) - 1 do
begin
keyword := elementbyindex(keywords, ki);
if MaterialList.IndexOf(EditorID(keyword)) > 0 then
begin
{ debug } if debugMsg then
addMessage('found valid keyword in ini');
CurrentMaterials := MaterialList.Objects[MaterialList.IndexOf(EditorID(keyword))];
ci := ObjectToElement(CurrentMaterials.Objects[0]);
if not EditorID(ci) = 'LeatherStrips' then
YggAdditem(recipeitems, ci, 1)
else
YggAdditem(recipeitems, ObjectToElement(CurrentMaterials.Objects[1]), 1);
end;
end;
end;
{ Debug } if debugMsg then
addMessage('[makeTemperable] Result := ' + EditorID(recipeTemper));
result := recipeTemper;
// Finalize
slTemp.Free;
debugMsg := false;
// End debugMsg section
end;
function isBlacklist(aRecord: IInterface): boolean;
var
slTemp : TStringList;
counter, i: integer;
word : string;
begin
counter := 0;
if not Assigned(DisKeyword) then
IniBlacklist;
for i := DisKeyword.Count - 1 downto 0 do
if HasKeyword(aRecord, DisKeyword[i]) then
begin
//addmessage('diskeyword');
counter := 1;
end;
if not Assigned(disWord) then
IniBlacklist;
word := LowerCase(EditorID(aRecord));
for i := disWord.Count - 1 downto 0 do
if ContainsText(word, disWord[i]) then
begin
//addmessage('disword');
counter := 1;
end;
word := LowerCase(name(aRecord));
for i := disWord.Count - 1 downto 0 do
if ContainsText(word, disWord[i]) then
begin
//addmessage('disword');
counter := 1;
end;
if disallowNP then
begin
if IntToStr(GetElementNativeValues(aRecord, 'Record Header\Record Flags\Non-Playable')) < 0 then
begin
//addmessage('NP');
counter := 1;
end;
if IntToStr(GetElementNativeValues(aRecord, 'DATA\Flags\Non-Playable')) < 0 then
begin
//addmessage('NP');
counter := 1;
end;
end;
if ignoreEmpty then
if not Assigned(ElementByPath(aRecord, 'FULL - Name')) then
begin
//addmessage('Noname');
counter := 1;
end;
if not IsWinningOVerride(aRecord) then
begin
//addmessage('loser');
counter := 1;
end;
if counter = 0 then
result := true
else
result := false;
end;
// Add get item count condition
procedure AddItemCondition(aRecord, aItem: IInterface; aCount: string);
var
conditions, condition: IInterface;
debugMsg : boolean;
begin
debugMsg := false;
{ Debug } if debugMsg then
addMessage('[AddItemCondition] AddItemCondition(' + EditorID(aRecord) + ', ' + EditorID(aItem) + ', ' + aCount + ');');
conditions := ElementByPath(aRecord, 'Conditions');
{ Debug } if debugMsg then
addMessage('[AddItemCondition] if not Assigned(conditions) :=' + BoolToStr(Assigned(conditions)) + ' then begin');
if not Assigned(conditions) then
begin
Add(aRecord, 'Conditions', true);
conditions := ElementByPath(aRecord, 'Conditions');
condition := ElementByPath(elementbyindex(conditions, 0), 'CTDA');
end
else
condition := ElementByPath(ElementAssign(conditions, HighInteger, nil, false), 'CTDA');
BeginUpdate(condition);
try
SetElementEditValues(condition, 'Type', '11000000'); // Greater than or equal to
SetElementEditValues(condition, 'Comparison Value', aCount + '.0');
SetElementEditValues(condition, 'Function', 'GetItemCount');
SetElementEditValues(condition, 'Inventory Object', ShortName(aItem));
finally
EndUpdate(condition);
end;
end;
// Add get item count condition
procedure AddGetItemCountCondition(rec: IInterface; s: string; aBoolean: boolean);
var
conditions, condition: IInterface;
begin
conditions := ElementByPath(rec, 'Conditions');
if not Assigned(conditions) then
begin
Add(rec, 'Conditions', true);
conditions := ElementByPath(rec, 'Conditions');
condition := ElementByPath(elementbyindex(conditions, 0), 'CTDA');
end
else
condition := ElementByPath(ElementAssign(conditions, HighInteger, nil, false), 'CTDA');
BeginUpdate(condition);
try
SetElementEditValues(condition, 'Type', '11000000'); // Greater than or equal to
SetElementEditValues(condition, 'Comparison Value', '1.0');
SetElementEditValues(condition, 'Function', 'GetItemCount');
SetElementEditValues(condition, 'Inventory Object', s);
finally
EndUpdate(condition);
end;
if aBoolean then
begin
condition := ElementByPath(ElementAssign(conditions, HighInteger, nil, false), 'CTDA');
BeginUpdate(condition);
try
SetElementEditValues(condition, 'Type', '10010000'); // Equal to / OR
SetElementEditValues(condition, 'Comparison Value', '0.0');
SetElementEditValues(condition, 'Function', 'GetEquipped');
SetElementEditValues(condition, 'Inventory Object', s);
finally
EndUpdate(condition);
end;
condition := ElementByPath(ElementAssign(conditions, HighInteger, nil, false), 'CTDA');
BeginUpdate(condition);
try
SetElementEditValues(condition, 'Type', '11000000'); // Greater than or equal to
SetElementEditValues(condition, 'Comparison Value', '2.0');
SetElementEditValues(condition, 'Function', 'GetItemCount');
SetElementEditValues(condition, 'Inventory Object', s);
finally
EndUpdate(condition);
end;
end;
end;
function MakeBreakdown(aRecord, aPlugin: IInterface): IInterface;
var
cobj, Items, item, recipeRecord, tempRecord : IInterface;
i, tempInteger, Count, LeatherCount, x, hc, rc: integer;
debugMsg, tempBoolean : boolean;
slTemp, slItem : TStringList;
edid : string;
begin
// Begin debugMsg section
debugMsg := false;
// Initialize
{ Debug } if debugMsg then
msgList('[MakeBreakdown] slGlobal := ', slGlobal, '');
{ Debug } if debugMsg then
addMessage('[MakeBreakdown] MakeBreakdown(' + EditorID(aRecord) + ', ' + GetFileName(aPlugin) + ' );');
slTemp := TStringList.Create;
slItem := TStringList.Create;
// Load crafting recipe or skip records that already have a breakdown recipe
for i := 0 to Pred(ReferencedByCount(aRecord)) do
begin
tempRecord := ReferencedByIndex(aRecord, i);
if (Signature(tempRecord) = 'COBJ') then
begin
if ContainsText(EditorID(tempRecord), 'Recipe') then
begin
{ Debug } if debugMsg then
addMessage('[MakeBreakdown] Crafting recipe: ' + EditorID(tempRecord));
cobj := tempRecord;
end
else
if ContainsText(EditorID(tempRecord), 'Breakdown') then
begin
{ Debug } if debugMsg then
addMessage('[MakeBreakdown] Breakdown already exists: ' + EditorID(tempRecord));
slTemp.Free;
slItem.Free;
exit;
end;
end;
end;
// Skip invalid records
{ Debug } if debugMsg then
addMessage('[MakeBreakdown] Skip invalid records');
tempBoolean := false;
if not Assigned(cobj) then
tempBoolean := true;
if not boolean(GetObject('BreakdownEnchanted', slGlobal)) then
if Assigned(ElementByPath(cobj, 'EITM')) then
tempBoolean := true;
if not boolean(GetObject('BreakdownDaedric', slGlobal)) then
if HasItem(cobj, 'DaedraHeart') then
tempBoolean := true;
if not boolean(GetObject('BreakdownDLC', slGlobal)) then
begin
slTemp.CommaText := 'DragonBone, DragonScales, DLC2ChitinPlate, ChaurusChitin, BoneMeal';
for i := 0 to slTemp.Count - 1 do
if HasItem(cobj, slTemp[i]) then
tempBoolean := true;
end;
if tempBoolean then
begin
slTemp.Free;
slItem.Free;
exit;
end;
// Common Function Output
{ Debug } if debugMsg then
addMessage('[MakeBreakdown] Common Function Output');
Items := ElementByPath(cobj, 'Items');
LeatherCount := 0;
// Process ingredients
{ Debug } if debugMsg then
addMessage('[MakeBreakdown] Process ingredients');
for i := 0 to Pred(ElementCount(Items)) do
begin
item := LinksTo(ElementByPath(elementbyindex(Items, i), 'CNTO - Item\Item'));
Count := GetElementEditValues(elementbyindex(Items, i), 'CNTO - Item\Count');
edid := EditorID(item);
{ Debug } if debugMsg then
addMessage('[MakeBreakdown] edid := ' + edid);
{ Debug } if debugMsg then
addMessage('[MakeBreakdown] count := ' + IntToStr(Count));
// if (edid = 'LeatherStrips') then Continue; // Why shouldn't leather strips be copied?
slTemp.CommaText := 'ingot, bone, scale, chitin, stalhrim';
for x := 0 to slTemp.Count - 1 do
if ContainsText(edid, slTemp[x]) then
slItem.addObject(name(item), Count);
if (edid = 'Leather01') then
LeatherCount := Count;
end;
{ Debug } if debugMsg then
msgList('[MakeBreakdown] slItem := ', slItem, '');
{ Debug } if debugMsg then
addMessage('[MakeBreakdown] LeatherCount := ' + IntToStr(LeatherCount));
// Create breakdown recipeRecord at smelter or tanning rack
{ Debug } if debugMsg then
addMessage('[MakeBreakdown] Create breakdown recipeRecord at smelter or tanning rack');
if (slItem.Count > 0) then
begin
// Create at smelter
{ Debug } if debugMsg then
addMessage('[MakeBreakdown] Create at smelter');
if (slItem.Count = 1) and (integer(slItem.Objects[0]) = 1) then
begin
// Skip making breakdown recipeRecord, can't produce less than 1 ingot
{ Debug } if debugMsg then
addMessage('[MakeBreakdown] Skip making breakdown recipeRecord, can''t produce less than 1 ingot');
end else begin
recipeRecord := Add(GroupBySignature(aPlugin, 'COBJ'), 'COBJ', true); { Debug }
if debugMsg then
addMessage('[MakeBreakdown] Make breakdown recipeRecord');
slTemp.CommaText := 'EDID, COCT, Items, CNAM, BNAM, NAM1'; { Debug }
if debugMsg then
addMessage('[MakeBreakdown] Add elements');
BeginUpdate(recipeRecord);
try
for i := 0 to slTemp.Count - 1 do
Add(recipeRecord, slTemp[i], true);
SetElementEditValues(recipeRecord, 'EDID', 'Breakdown' + StrCapFirst(Signature(aRecord)) + '_' + Trim(RemoveSpaces(RemoveFileSuffix(GetFileName(GetFile(aRecord))))) + '_' + Trim(EditorID(aRecord)));
SetElementNativeValues(recipeRecord, 'BNAM', $000A5CCE); // CraftingSmelter
finally
EndUpdate(recipeRecord);
end;
AddGetItemCountCondition(recipeRecord, ShortName(aRecord), boolean(GetObject('BreakdownEquipped', slGlobal)));
// Add items
{ Debug } if debugMsg then
addMessage('[MakeBreakdown] Add items');
Items := ElementByPath(recipeRecord, 'Items');
item := elementbyindex(Items, 0);
SetElementEditValues(item, 'CNTO - Item\Item', ShortName(aRecord));
SetElementEditValues(item, 'CNTO - Item\Count', 1);
SetElementEditValues(recipeRecord, 'COCT', 1);
// Set created object stuff
hc := 0;
x := -1;
for i := 0 to slItem.Count - 1 do
begin
// Skip single items
// if (Integer(slItem.Objects[i])-1 <= 0) then Continue;
// Use first Item subelement or create new one
if (integer(slItem.Objects[i]) >= hc) then
begin
hc := integer();
x := i;
end;
end;
if (x > -1) then
begin
SetElementEditValues(recipeRecord, 'CNAM', slItem[x]);
tempInteger := integer(slItem.Objects[x]) - 1;
if (tempInteger = 0) then
tempInteger := 1;
SetElementEditValues(recipeRecord, 'NAM1', tempInteger);
end else begin
{ Debug } if debugMsg then
addMessage('[MakeBreakdown] Remove(recipeRecord)');
Remove(recipeRecord);
end;
Inc(rc);
end;
end
else
if (LeatherCount > 0) then
begin { Debug }
if debugMsg then
addMessage('[MakeBreakdown] Create at tanning rack');
recipeRecord := Add(GroupBySignature(aPlugin, 'COBJ'), 'COBJ', true);
slTemp.CommaText := 'EDID, COCT, Items, CNAM, BNAM, NAM1';
BeginUpdate(recipeRecord);
try
for i := 0 to slTemp.Count - 1 do
Add(recipeRecord, slTemp[i], true);
SetElementEditValues(recipeRecord, 'EDID', 'Breakdown' + StrCapFirst(Signature(aRecord)) + '_' + Trim(RemoveSpaces(RemoveFileSuffix(GetFileName(GetFile(aRecord))))) + '_' + Trim(EditorID(aRecord)));
SetElementNativeValues(recipeRecord, 'BNAM', $0007866A); // CraftingTanningRack
AddGetItemCountCondition(recipeRecord, ShortName(aRecord), boolean(GetObject('BreakdownEquipped', slGlobal)));
// Add items to recipeRecord
Items := ElementByPath(recipeRecord, 'Items');
item := elementbyindex(Items, 0);
SetElementEditValues(item, 'CNTO - Item\Item', ShortName(aRecord));
SetElementEditValues(item, 'CNTO - Item\Count', 1);
SetElementEditValues(recipeRecord, 'COCT', 1);
// Set created object stuff
SetElementNativeValues(recipeRecord, 'CNAM', $000800E4); // LeatherStrips
SetElementEditValues(recipeRecord, 'NAM1', 2);
finally
EndUpdate(recipeRecord);
end;
Inc(rc);
end;
// Finalize
slTemp.Free;
slItem.Free;
debugMsg := false;
// End debugMsg section
end;
// Shifts all TForm components up or down
procedure TShift(aInteger, bInteger: integer; aForm: TForm; aBoolean: boolean);
var
debugMsg: boolean;
i : integer;
begin
for i := 0 to aForm.ComponentCount - 1 do
begin
if (aForm.Components[i].Top >= aInteger) then
begin
if aBoolean then
begin
aForm.Components[i].Top := aForm.Components[i].Top - bInteger;
end else begin
aForm.Components[i].Top := aForm.Components[i].Top + bInteger;
end;
end;
end;
end;
// Checks if an input record has an item matching the input EditorID.
function HasItem(aRecord: IInterface; s: string): boolean;
var
name : string;
Items, li: IInterface;
i : integer;
begin
result := false;
Items := ElementByPath(aRecord, 'Items');
if not Assigned(Items) then
exit;
for i := 0 to Pred(ElementCount(Items)) do
begin
li := elementbyindex(Items, i);
name := EditorID(LinksTo(ElementByPath(li, 'CNTO - Item\Item')));
if (name = s) then
begin
result := true;
break;
end;
end;
end;
// Clears empty TStringList entries
procedure slClearEmptyStrings(aList: TStringList);
var
slTemp: TStringList;
i : integer;
begin
// Initialize
slTemp := TStringList.Create;
// Process
for i := 0 to aList.Count - 1 do
if (aList[i] = '') then
slTemp.Add(aList[i]);
for i := 0 to slTemp.Count - 1 do
if (aList.IndexOf(slTemp[i]) >= 0) then
aList.Delete(aList.IndexOf(slTemp[i]));
// Finalize
slTemp.Free;
end;
// Removes an entry that contains substr
procedure slDeleteString(s: string; aList: TStringList);
var
i, tempInteger: integer;
slTemp : TStringList;
begin
// Initialize
slTemp := TStringList.Create;
// Process
if StrWithinSL(s, aList) then
begin
for i := 0 to aList.Count - 1 do
if ContainsText(aList[i], s) then
slTemp.Add(aList[i]);
for i := 0 to slTemp.Count - 1 do
if (aList.IndexOf(slTemp[i]) >= 0) then
aList.Delete(aList.IndexOf(slTemp[i]));
end;
// Finalize
slTemp.Free;
end;
// Gets an object associated with a string
function GetObject(s: string; aList: TStringList): TObject;
var
tempString: string;
debugMsg : boolean;
i : integer;
begin
// Begin debugMsg section
debugMsg := false;
{ Debug } if debugMsg then
addMessage('[GetObject] GetObject(' + s + ', aList );');
{ Debug } if debugMsg then
msgList('[GetObject] aList := ', aList, '');
if slContains(slGlobal, s) then
result := aList.Objects[aList.IndexOf(s)];
debugMsg := false;
// End debugMsg section
end;
// Gets an object associated with a string
function StringObject(s: string; aList: TStringList): string;
var
tempString: string;
debugMsg : boolean;
i : integer;
begin
// Begin debugMsg section
debugMsg := false;
{ Debug } if debugMsg then
addMessage('[GetObject] GetObject(' + s + ', aList );');
{ Debug } if debugMsg then
msgList('[GetObject] aList := ', aList, '');
for i := 0 to aList.Count - 1 do
begin
if ContainsText(aList[i], s) then
begin
result := StrPosCopy(aList[i], '=', false);
{ Debug } if debugMsg then
addMessage('[GetObject] Result := ' + result);
exit;
end;
end;
debugMsg := false;
// End debugMsg section
end;
// Removes an entry that contains substr
procedure SetObject(s: string; aObject: Variant; aList: TStringList);
var
i, tempInteger: integer;
debugMsg : boolean;
begin
// Begin debugMsg Section
debugMsg := false;
{ Debug } if debugMsg then
addMessage('[SetObject] SetObject(' + s + ', aObject, aList );');
{ Debug } if debugMsg then
addMessage('[SetObject] aObject := ' + varTypeAsText(aObject));
{ Debug } if debugMsg then
msgList('[SetObject] aList := ', aList, '');
tempInteger := aList.IndexOf(s);
if (tempInteger < 0) then
begin
for i := 0 to aList.Count - 1 do
begin
if (aList[i] = s) then
begin
tempInteger := i;
break;
end;
end;
end;
if (tempInteger > -1) then
begin
aList.Objects[tempInteger] := aObject;
end else begin
aList.addObject(s, aObject);
end;
debugMsg := false;
// End debugMsg section
end;
// Gets the component associated with a caption
function AssociatedComponent(s: string; frm: TForm): TObject;
begin
result := ComponentByTop(ComponentByCaption(s, frm).Top - 2, frm)
end;
function PreviousOverrideExists(aRecord: IInterface; LoadOrder: integer): boolean;
var
debugMsg, tempBoolean: boolean;
tempRecord : IInterface;
i : integer;
begin
// Begin debugMsg section
debugMsg := false;
result := false;
if (OverrideCount(aRecord) > 0) then
begin
tempBoolean := false;
for y := Pred(OverrideCount(aRecord)) downto 0 do
begin
tempRecord := OverrideByIndex(aRecord, y);
if (LoadOrder >= GetLoadOrder(GetFile(tempRecord))) then
begin
{ Debug } if debugMsg then
addMessage('[PreviousOverrideExists] ' + EditorID(tempRecord) + ' := ' + IntToStr(LoadOrder) + ' >= ' + IntToStr(GetLoadOrder(GetFile(tempRecord))));
result := true;
exit;
end;
end;
end;
debugMsg := false;
// End debugMsg section
end;
function GetPreviousOverride(aRecord: IInterface; LoadOrder: integer): IInterface;
var
debugMsg, tempBoolean: boolean;
tempRecord : IInterface;
i, y : integer;
begin
// Begin debugMsg section
debugMsg := false;
result := nil;
if (OverrideCount(aRecord) > 0) then
begin
tempBoolean := false;
for y := Pred(OverrideCount(aRecord)) downto 0 do
begin
tempRecord := OverrideByIndex(aRecord, y);
if (LoadOrder >= GetLoadOrder(GetFile(tempRecord))) then
begin
{ Debug } if debugMsg then
addMessage('[PreviousOverrideExists] ' + EditorID(tempRecord) + ' := ' + IntToStr(LoadOrder) + ' >= ' + IntToStr(GetLoadOrder(GetFile(tempRecord))));
result := tempRecord;
exit;
end;
end;
end;
debugMsg := false;
// End debugMsg section
end;
function HasFileOverride(aRecord, aFile: IInterface): boolean;
var
debugMsg : boolean;
tempRecord: IInterface;
i, y : integer;
begin
// Begin debugMsg section
debugMsg := false;
result := false;
if (OverrideCount(aRecord) > 0) then
begin
for y := Pred(OverrideCount(aRecord)) downto 0 do
begin
tempRecord := OverrideByIndex(aRecord, y);
if (GetLoadOrder(aFile) = GetLoadOrder(GetFile(tempRecord))) then
begin
{ Debug } if debugMsg then
addMessage('[PreviousOverrideExists] ' + EditorID(tempRecord) + ' := ' + IntToStr(GetLoadOrder(aFile)) + ' >= ' + IntToStr(GetLoadOrder(GetFile(tempRecord))));
result := true;
exit;
end;
end;
end;
debugMsg := false;
// End debugMsg section
end;
function GetFileOverride(aRecord, aFile: IInterface): IInterface;
var
debugMsg, tempBoolean: boolean;
tempRecord : IInterface;
i, y : integer;
begin
// Begin debugMsg section
debugMsg := false;
result := nil;
if (OverrideCount(aRecord) > 0) then
begin
tempBoolean := false;
for y := Pred(OverrideCount(aRecord)) downto 0 do
begin
tempRecord := OverrideByIndex(aRecord, y);
if (GetLoadOrder(aFile) = GetLoadOrder(GetFile(tempRecord))) then
begin
{ Debug } if debugMsg then
addMessage('[PreviousOverrideExists] ' + EditorID(tempRecord) + ' := ' + IntToStr(GetLoadOrder(aFile)) + ' >= ' + IntToStr(GetLoadOrder(GetFile(tempRecord))));
result := tempRecord;
exit;
end;
end;
end;
debugMsg := false;
// End debugMsg section
end;
function GetEnchLevel(objEffect: IInterface; slItemTiers: TStringList): integer;
var
debugMsg, tempBoolean: boolean;
tempString : string;
i : integer;
begin
// Initialize
debugMsg := false;
{ Debug } if debugMsg then
msgList('[GetEnchLevel] GetEnchLevel(' + EditorID(objEffect) + ', ', slItemTiers, ' );');
{ Debug } if debugMsg then
for i := 0 to slItemTiers.Count - 1 do
addMessage('[GetEnchLevel] slItemTiers[' + IntToStr(i + 1) + '] := ' + IntToStr(integer(slItemTiers.Objects[i])) + ';');
result := -1;
// Process
tempString := Copy(EditorID(objEffect), Length(EditorID(objEffect)) - 1, 2);
{ Debug } if debugMsg then
addMessage('[GetEnchLevel] tempString := ' + tempString);
if slContains(slItemTiers, tempString) then
begin
result := integer(slItemTiers.Objects[slItemTiers.IndexOf(tempString)]);
// This is specifically for 'More Interesting Loot' enchantments
end
else
if (Copy(EditorID(objEffect), 1, 2) = 'aa') then
begin
tempString := EditorID(objEffect);
if (Length(IntToStr(IntWithinStr(tempString))) = 1) then
begin
for i := 1 to 6 do
begin
if slContains(slItemTiers, '0' + IntToStr(i)) then
begin
result := slItemTiers.Objects[slItemTiers.IndexOf('0' + IntToStr(i))]
end
else
result := slItemTiers.Objects[slItemTiers.Count - 1];
end;
end
else
if (IntWithinStr(tempString) = 10) then
begin
result := slItemTiers.Objects[0];
end
else
if (IntWithinStr(tempString) > 50) and (IntWithinStr(tempString) < 100) then
begin
result := slItemTiers.Objects[slItemTiers.Count - 1];
end
else
if (IntWithinStr(tempString) > 100) and (IntWithinStr(tempString) <= 200) then
begin
if ContainsText(tempString, 'Greater') then
begin
result := slItemTiers.Objects[slItemTiers.Count - 1];
end
else
result := slItemTiers.Objects[(slItemTiers.Count div 2)];
end else begin
result := IntWithinStr(tempString);
end;
end;
{ Debug } if debugMsg then
addMessage('[GetEnchLevel] Result := ' + IntToStr(result) + ';');
if (result = 0) then
result := 1;
end;
// A copy function that allows you to copy from one position to another [mte functions]
function StrPosCopyBtwn(inputString, aString, bString: string): string;
var
i, p1, p2: integer;
debugMsg : boolean;
begin
// Begin debugMsg section
debugMsg := false;
result := '';
result := StrPosCopy(StrPosCopy(inputString, aString, false), bString, true);
{ Debug } if debugMsg then
addMessage('[StrPosCopyBtwn] Result := ' + result);
debugMsg := false;
// End debugMsg section
end;
procedure GenderOnlyArmor(aString: string; aRecord, aPlugin: IInterface);
var
tempRecord, tempelement, copyRecord, armorAddonRecord, armorAddonCopy, templateRecord, templateAddonRecord, Races: IInterface;
slTemp : TStringList;
debugMsg, LoadOrder : boolean;
i : integer;
begin
// Initialize
debugMsg := false;
LoadOrder := false;
aRecord := WinningOverride(aRecord);
slTemp := TStringList.Create;
{ Debug } if debugMsg then
addMessage('[GenderOnlyArmor] GenderOnlyArmor(' + aString + ', ' + EditorID(aRecord) + ', ' + GetFileName(aPlugin) + ' );');
if not((aString = 'Male') or (aString = 'Female')) then
begin
addMessage('[GenderOnlyArmor] ' + aString + ' not ''Male'' or ''Female''');
exit;
end;
if (GetPrimarySlot(aRecord) = '00') then
exit;
templateRecord := ObjectToElement(GetObject(EditorID(aRecord) + 'Template', slGlobal));
copyRecord := aRecord; { Debug }
if debugMsg then
addMessage('[GenderOnlyArmor] copyRecord := ' + EditorID(aRecord));
armorAddonRecord := LinksTo(ElementByPath(aRecord, 'Armature\MODL')); { Debug }
if debugMsg then
addMessage('[GenderOnlyArmor] armorAddonRecord := ' + EditorID(armorAddonRecord));
if (GetLoadOrder(GetFile(aRecord)) = GetLoadOrder(aPlugin)) then
LoadOrder := true; // Specifies if an Override is generated
// Process
{ Debug } if debugMsg then
addMessage('[GenderOnlyArmor] if ContainsText(aString, Female) then begin := ' + BoolToStr(ContainsText(aString, 'Female')));
if (aString = 'Male') then
begin
{ Debug } if debugMsg then
addMessage('[GenderOnlyArmor] Male-Only Armor Detected');
// Worn Armor (Armor Addon)
if not(Length(GetElementEditValues(armorAddonRecord, 'Female world model\MOD3')) > 0) then
begin
if not LoadOrder then
armorAddonRecord := wbCopyElementToFile(LinksTo(ElementByPath(aRecord, 'Armature\MODL')), aPlugin, false, true);
Add(armorAddonRecord, 'Female world model', true);
Add(armorAddonRecord, 'Female world model\MOD3', true);
SetElementEditValues(armorAddonRecord, 'Female world model\MOD3', GetElementEditValues(WinningOverride(templateRecord), 'Female world model\MOD3'));
if not(Length(GetElementEditValues(armorAddonRecord, 'Female world model\MOD3')) > 0) then
SetElementEditValues(armorAddonRecord, 'Female world model\MOD3', GetElementEditValues(WinningOverride(templateRecord), 'Male world model\MOD2'));
end;
// Remove ElderRace
for i := 0 to Pred(ElementCount(ElementByPath(armorAddonRecord, 'Additional Races'))) do
begin
if ContainsText(GetEditValue(elementbyindex(ElementByPath(armorAddonRecord, 'Additional Races'), i)), 'ElderRace') then
begin
armorAddonCopy := MainRecordByEditorID(GroupBySignature(aPlugin, 'ARMO'), EditorID(armorAddonRecord));
if not Assigned(armorAddonCopy) then
armorAddonCopy := wbCopyElementToFile(armorAddonRecord, aPlugin, false, true);
{ Debug } if debugMsg then
addMessage('[GenderOnlyArmor] GetEditValue(elementbyindex(ElementByPath(armorAddonCopy, ' Additional Races '), i)) := ' + GetEditValue(elementbyindex(ElementByPath(armorAddonCopy, 'Additional Races'), i)));
slTemp.Add(GetEditValue(elementbyindex(ElementByPath(armorAddonCopy, 'Additional Races'), i)));
Remove(elementbyindex(ElementByPath(armorAddonCopy, 'Additional Races'), i));
end;
end;
// Ground Armor
if not(Length(GetElementEditValues(aRecord, 'Female world model\MOD4')) > 0) then
begin
if not LoadOrder then
copyRecord := wbCopyElementToFile(aRecord, aPlugin, false, true);
Add(copyRecord, 'Female world model', true);
Add(copyRecord, 'Female world model\MOD4', true);
SetElementEditValues(copyRecord, 'Female world model\MOD4', GetElementEditValues(WinningOverride(templateRecord), 'Female world model\MOD4'));
if not(Length(GetElementEditValues(copyRecord, 'Female world model\MOD4')) > 0) then
SetElementEditValues(copyRecord, 'Female world model\MOD4', GetElementEditValues(WinningOverride(templateRecord), 'Male world model\MOD2'));
end;
end
else
if ContainsText(aString, 'Female') then
begin
{ Debug } if debugMsg then
addMessage('[GenderOnlyArmor] Female-Only Armor Detected');
// Worn Armor (Armor Addon)
if not(Length(GetElementEditValues(armorAddonRecord, 'Male world model\MOD2')) > 0) then
begin { Debug }
if debugMsg then
addMessage('[GenderOnlyArmor] Worn Armor Begin');
if not LoadOrder then
armorAddonRecord := wbCopyElementToFile(LinksTo(ElementByPath(aRecord, 'Armature\MODL')), aPlugin, false, true);
Add(armorAddonRecord, 'Male world model', true);
Add(armorAddonRecord, 'Male world model\MOD2', true);
SetElementEditValues(armorAddonRecord, 'Male world model\MOD2', GetElementEditValues(LinksTo(ElementByPath(WinningOverride(templateRecord), 'Armature\MODL')), 'Male world model\MOD2'));
end;
// Remove ElderRace
for i := 0 to Pred(ElementCount(ElementByPath(armorAddonRecord, 'Additional Races'))) do
begin
if ContainsText(GetEditValue(elementbyindex(ElementByPath(armorAddonRecord, 'Additional Races'), i)), 'ElderRace') then
begin
armorAddonCopy := MainRecordByEditorID(GroupBySignature(aPlugin, 'ARMO'), EditorID(armorAddonRecord));
if not Assigned(armorAddonCopy) then
armorAddonCopy := wbCopyElementToFile(armorAddonRecord, aPlugin, false, true);
{ Debug } if debugMsg then
addMessage('[GenderOnlyArmor] GetEditValue(elementbyindex(ElementByPath(armorAddonCopy, ''Additional Races''), i)) := ' + GetEditValue(elementbyindex(ElementByPath(armorAddonCopy, 'Additional Races'), i)));
slTemp.Add(GetEditValue(elementbyindex(ElementByPath(armorAddonCopy, 'Additional Races'), i)));
Remove(elementbyindex(ElementByPath(armorAddonCopy, 'Additional Races'), i));
end;
end;
// Ground Armor
{ Debug } if debugMsg then
addMessage('[GenderOnlyArmor] GetElementEditValues(aRecord, Male world model\MOD2) := ' + GetElementEditValues(aRecord, 'Male world model\MOD2'));
if not(Length(GetElementEditValues(aRecord, 'Male world model\MOD2')) > 0) then
begin
if not LoadOrder then
copyRecord := wbCopyElementToFile(aRecord, aPlugin, false, true);
Add(copyRecord, 'Male world model', true);
Add(copyRecord, 'Male world model\MOD2', true);
SetElementEditValues(copyRecord, 'Male world model\MOD2', GetElementEditValues(WinningOverride(templateRecord), 'Male world model\MOD2'));
end;
end
else
addMessage('[GenderOnlyArmor] aString := ' + aString + ' does not contain ''Male'' or ''Female''');
// Create a new Armor Addon for ElderRace
if (slTemp.Count > 0) then
begin
{ Debug } if debugMsg then
addMessage('[GenderOnlyArmor] Create a new Armor Addon for ElderRace');
{ Debug } if debugMsg then
msgList('[GenderOnlyArmor] slTemp := ', slTemp, '');
templateAddonRecord := wbCopyElementToFile(LinksTo(ElementByPath(templateRecord, 'Armature\MODL')), aPlugin, true, true);
SetElementEditValues(templateAddonRecord, 'EDID', EditorID(armorAddonRecord) + '_OldPeople');
{ Debug } if debugMsg then
addMessage('[GenderOnlyArmor] templateAddonRecord := ' + EditorID(templateAddonRecord));
RefreshList(templateAddonRecord, 'Additional Races');
for i := 0 to slTemp.Count - 1 do
begin
tempelement := ElementAssign(ElementByPath(templateAddonRecord, 'Additional Races'), HighInteger, nil, false);
SetEditValue(tempelement, slTemp[i]);
end;
RemoveInvalidEntries(templateAddonRecord);
if not(GetLoadOrder(GetFile(copyRecord)) = GetLoadOrder(aPlugin)) then
copyRecord := wbCopyElementToFile(aRecord, aPlugin, false, true);
tempelement := ElementAssign(ElementByPath(copyRecord, 'Armature'), HighInteger, nil, false);
SetEditValue(tempelement, name(templateAddonRecord));
end;
// Finalize
slTemp.Free;
end;
function IsFemaleOnly(aRecord: IInterface): boolean;
begin
result := false;
if not(Length(GetElementEditValues(aRecord, 'Male world model\MOD2')) > 0) then
result := true;
if not(Length(GetElementEditValues(LinksTo(ElementByPath(aRecord, 'Armature\MODL')), 'Male world model\MOD2')) > 0) then
result := true;
end;
function HasGenderKeyword(aRecord: IInterface): boolean;
begin
if (textInKeyword(aRecord, 'male', false)) or (textInKeyword(aRecord, 'female', false)) then
result := true
else
result := false;
end;
function GetGenderFromKeyword(aRecord: IInterface): string;
begin
result := '';
if textInKeyword(aRecord, 'female', false) then
result := 'Female'
else
if textInKeyword(aRecord, 'male', false) then
result := 'Male';
end;
function IsClothing(aRecord: IInterface): boolean;
var
tempString: string;
begin
result := false;
if not(Signature(aRecord) = 'ARMO') then
exit;
if ElementExists(aRecord, 'BODT') then
begin
tempString := 'BODT';
end
else
tempString := 'BOD2';
if (GetElementEditValues(aRecord, tempString + '\Armor Type') = 'Clothing') then
begin
result := true;
exit;
end;
if ContainsText(EditorID(aRecord), 'Clothing') then
begin
result := true;
exit;
end;
if textInKeyword(aRecord, 'clothing', false) then
result := true;
if ElementExists(aRecord, 'DNAM') then
begin
if (GetElementNativeValues(aRecord, 'DNAM') = 0) then
begin
result := true;
exit;
end;
end
else
result := true;
end;
function textInKeyword(aRecord: IInterface; Text: string; checkCaps: boolean): boolean;
var
keywords : IInterface;
tempString: string;
i : integer;
begin
result := false;
if not checkCaps then
Text := LowerCase(Text);
keywords := ElementByPath(aRecord, 'KWDA');
for i := 0 to ElementCount(keywords) - 1 do
begin
tempString := EditorID(LinksTo(elementbyindex(keywords, i)));
if not checkCaps then
tempString := LowerCase(tempString);
if ContainsText(tempString, Text) then
begin
result := true;
exit;
end;
end;
end;
function MostCommonString(aList: TStringList): string;
var
i, x, tempInteger, Count: integer;
slTemp : TStringList;
debugMsg : boolean;
begin
// Begin debugMsg Section
debugMsg := false;
// Initialize
if debugMsg then
msgList('[MostCommonString] MostCommonString(', aList, ');');
slTemp := TStringList.Create;
// Process
tempInteger := 0;
for i := 0 to aList.Count - 1 do
begin
if slContains(slTemp, aList[i]) then
Continue;
Count := 0;
for x := 0 to aList.Count - 1 do
if (aList[x] = aList[i]) and (x <> i) then
Inc(Count);
if (Count > tempInteger) and (Count > 1) then
begin
result := aList[i];
tempInteger := Count;
end;
slTemp.Add(aList[i]);
end;
// Finalize
if debugMsg then
addMessage('[MostCommonString] Result := ' + result);
slTemp.Free;
debugMsg := false;
// End debugMsg Section
end;
function GetElementType(aRecord: IInterface): string;
var
debugMsg: boolean;
begin
debugMsg := false;
{ Debug } if debugMsg then
addMessage('[GetElementType] GetElementType(' + EditorID(aRecord) + ' );');
{ Debug } if debugMsg then
addMessage('[GetElementType] Signature(' + EditorID(aRecord) + ' := ' + Signature(aRecord));
if (Signature(aRecord) = 'ARMO') then
begin
if ElementExists(aRecord, 'BODT') then
begin
result := 'BODT';
end
else
result := 'BOD2';
end
else
if (Signature(aRecord) = 'LVLI') then
result := 'LVLF';
end;
function TimeBtwn(Start, Stop: TDateTime): integer;
begin
result := ((3600 * GetHours(Stop)) + (60 * GetMinutes(Stop)) + GetSeconds(Stop)) - ((3600 * GetHours(Start)) + (60 * GetMinutes(Start)) + GetSeconds(Start));
end;
function GetSeconds(aTime: TDateTime): integer;
var
tempString: string;
begin
tempString := TimeToStr(aTime);
result := StrToInt(Trim(IntWithinStr(StrPosCopy(StrPosCopy(tempString, ':', false), ':', false))));
end;
function GetMinutes(aTime: TDateTime): integer;
begin
result := StrToInt(Trim(StrPosCopy(StrPosCopy(TimeToStr(aTime), ':', false), ':', true)));
end;
function GetHours(aTime: TDateTime): integer;
begin
result := StrToInt(Trim(StrPosCopy(TimeToStr(aTime), ':', true)));
end;
function IntegerToTime(TotalTime: integer): string;
var
TimeInteger, Hours, Minutes, Seconds : integer;
stringHours, stringMinutes, stringSeconds: string;
tempString : string;
begin
TimeInteger := TotalTime;
// Hours
while (TimeInteger > 3600) do
begin
TimeInteger := TimeInteger - 3600;
Hours := Hours + 1;
end;
if (Hours <= 0) then
begin
stringHours := '00';
end
else
if (Hours < 10) then
stringHours := '0' + IntToStr(Hours)
else
stringHours := IntToStr(Hours);
// Minutes
while (TimeInteger > 60) do
begin
TimeInteger := TimeInteger - 60;
Minutes := Minutes + 1;
end;
if (Minutes <= 0) then
begin
stringMinutes := '00';
end
else
if (Minutes < 10) then
stringMinutes := '0' + IntToStr(Minutes)
else
stringMinutes := IntToStr(Minutes);
// Seconds
if (TimeInteger <= 0) then
begin
stringSeconds := '00';
end
else
if (TimeInteger < 10) then
stringSeconds := '0' + IntToStr(TimeInteger)
else
stringSeconds := IntToStr(TimeInteger);
result := stringHours + ':' + stringMinutes + ':' + stringSeconds;
end;
procedure addProcessTime(aFunctionName: string; aTime: integer);
begin
SetObject(aFunctionName, integer(GetObject(aFunctionName, slProcessTime)) + aTime, slProcessTime);
end;
function StrToOrd(aString: string): Int64;
var
i, aLength: integer;
begin
aLength := Length(aString);
if (aLength > 9) then
aString := Copy(aString, 1, 9);
for i := 0 to aLength do
result := result * 100 + ord(Copy(aString, i, 1));
end;
function GetPrimarySlot(aRecord: IInterface): string;
var
slTemp, slBOD2: TStringList;
debugMsg : boolean;
i : integer;
begin
// Initialize
debugMsg := false;
{ Debug } if debugMsg then
addMessage('[GetPrimarySlot] GetPrimarySlot(' + EditorID(aRecord) + ' );');
result := '00';
slBOD2 := TStringList.Create;
slTemp := TStringList.Create;
// Process
slGetFlagValues(aRecord, slBOD2, false);
{ Debug } if debugMsg then
msgList('[GetPrimarySlot] slGetFlagValues := ', slBOD2, '');
slTemp.CommaText := '30, 32, 33, 35, 36, 37, 39, 42';
for i := 0 to slTemp.Count - 1 do
begin
if slContains(slBOD2, slTemp[i]) then
begin
result := slTemp[i];
break;
end;
end;
{ Debug } if debugMsg then
addMessage('[GetPrimarySlot] Result := ' + result);
// Finalize
slBOD2.Free;
slTemp.Free;
end;
procedure RemoveSubStr(aList: TStringList; aString: string);
var
debugMsg: boolean;
Count : integer;
begin
debugMsg := false;
{ Debug } if debugMsg then
msgList('[RemoveSubStr] RemoveSubStr(', aList, ', ' + aString + ' );');
Count := 0;
while (aList.Count > Count) do
begin
while ContainsText(aList[Count], aString) do
begin
aList[Count] := Trim(Trim(StrPosCopy(aList[Count], aString, true)) + ' ' + Trim(StrPosCopy(aList[Count], aString, false)));
{ Debug } if debugMsg then
addMessage('[RemoveSubStr] aList[Count] := ' + aList[Count]);
end;
Inc(Count);
end;
end;
procedure AddPrimarySlots(aList: TStringList);
var
tempString: string;
i : integer;
begin
for i := 0 to aList.Count - 1 do
begin // Associate current item with a primary slot
tempString := AssociatedBOD2(aList[i]);
if not slContains(aList, tempString) then
aList.Add(tempString);
end;
end;
function StrEndsWithInteger(aString: string): boolean;
var
slTemp : TStringList;
debugMsg: boolean;
i : integer;
begin
// Begin debugMsg section
debugMsg := false;
slTemp := TStringList.Create;
slTemp.CommaText := '0, 1, 2, 3, 4, 5, 6, 7, 8, 9';
result := true;
for i := 0 to slTemp.Count - 1 do
begin
if StrEndsWith(aString, slTemp[i]) then
begin
slTemp.Free;
exit;
end;
end;
result := false;
slTemp.Free;
end;
function FinalCharacter(aString: string): string;
begin
result := RightStr(aString, 1);
end;
function RemoveFinalCharacter(aString: string): string;
var
debugMsg: boolean;
begin
result := Copy(aString, 0, Length(aString) - 1);
end;
// stuff below this is probably added by yggdrasil75
function AddMasterBySignature(Signature: string; Patch: IInterface): integer;
var
i : integer;
temp : IInterface;
debugMsg: boolean;
begin
debugMsg := false;
{ Debug } if debugMsg then
addMessage('Adding Masters with ' + Signature);
for i := 0 to FileCount - 1 do
begin
temp := FileByIndex(i);
if Pos(GetFileName(Patch), GetFileName(temp)) < 1 then
begin
if HasGroup(temp, Signature) then
begin
AddMasterIfMissing(Patch, GetFileName(temp));
end;
end;
end;
end;
function GatherMaterials: integer;
var
TempList : TStringList;
FileIndex, GroupIndex, f : integer;
CurrentFile, CurrentGroup, CurrentKYWD: IInterface;
begin
MaterialList := TStringList.Create;
MaterialList.Sorted := true;
MaterialList.Duplicates := dupIgnore;
MaterialList.NameValueSeparator := ';';
for FileIndex := 0 to FileCount - 1 do
begin
CurrentFile := FileByIndex(FileIndex);
if HasGroup(CurrentFile, 'KYWD') then
begin
CurrentGroup := GroupBySignature(CurrentFile, 'KYWD');
for GroupIndex := 0 to ElementCount(CurrentGroup) - 1 do
begin
CurrentKYWD := EditorID(elementbyindex(CurrentGroup, GroupIndex));
if Pos('material', LowerCase(CurrentKYWD)) > 0 then
begin
MaterialList.Add(CurrentKYWD);
end
else
if Pos('materiel', LowerCase(CurrentKYWD)) > 0 then
begin
MaterialList.Add(CurrentKYWD);
end
else
if Pos('clothing', LowerCase(CurrentKYWD)) > 0 then
begin
MaterialList.Add(CurrentKYWD);
end;
end;
end;
end;
TempList := TStringList.Create;
TempList.DelimitedText := Ini.ReadString('Crafting', 'sKYWDList', '');
if firstRun then
begin
for f := 0 to TempList.Count - 1 do
begin
MaterialListPrinter(TempList.strings[f]);
end;
end;
IniToMatList;
for f := MaterialList.Count - 1 downto 0 do
begin
if TempList.IndexOf(MaterialList.strings[f]) < 0 then
MaterialListPrinter(MaterialList.strings[f]);
end;
MaterialList.AddStrings(TempList);
TempList.Free;
TempList.clear;
Ini.WriteString('Crafting', 'sKYWDList', MaterialList.CommaText);
Ini.UpdateFile;
end;
function MaterialListPrinter(CurrentKYWDName: string): integer;
var
invalidStuff, ValidSignatures, Output, Input, TempList: TStringList;
edid, TempSig : string;
item, CurrentKYWD, CurrentItem, CurrentReference : IInterface;
ItemIndex, RecipeCount, k, a, i, l, LimitIndex : integer;
y, amount, limit : Double;
debugMsg : boolean;
begin
debugMsg := false;
ValidSignatures := TStringList.Create;
ValidSignatures.DelimitedText := 'AMMO,ARMO,WEAP';
invalidStuff := TStringList.Create;
invalidStuff.DelimitedText := 'ARMO,AMMO,WEAP,SLGM,BOOK';
Input := TStringList.Create;
Output := TStringList.Create;
CurrentKYWD := TrueRecordByEDID(CurrentKYWDName);
if not Assigned(CurrentKYWD) then
exit;
RecipeCount := 0;
for k := ReferencedByCount(CurrentKYWD) - 1 downto 0 do
begin
{ Debug } if debugMsg then
addMessage('Cycle ' + IntToStr(k) + ' for kywd ' + CurrentKYWDName);
CurrentItem := ReferencedByIndex(CurrentKYWD, k);
TempSig := Signature(CurrentItem);
if ValidSignatures.IndexOf(TempSig) < 0 then
Continue;
if not isBlacklist(CurrentItem) then
Continue;
{ Debug } if debugMsg then
addMessage('Passed Signature');
for a := ReferencedByCount(CurrentItem) - 1 downto 0 do
begin
{ Debug } if debugMsg then
addMessage('Recipe Search ' + IntToStr(a));
CurrentReference := ReferencedByIndex(CurrentItem, a);
if not Pos('COBJ', Signature(CurrentReference)) > 0 then
Continue;
{ Debug } if debugMsg then
addMessage('it is a recipe');
if not equals(CurrentItem, LinksTo(ElementByPath(CurrentReference, 'CNAM'))) then
Continue;
{ Debug } if debugMsg then
addMessage('item is output');
if not IsWinningOVerride(CurrentReference) then
Continue;
if Length(GetElementEditValues(CurrentReference, 'COCT')) = 0 then
Continue
else
l := StrToInt64Def(GetElementEditValues(CurrentReference, 'COCT'), 0) - 1;
{ Debug } if debugMsg then
addMessage('standard recipe limitations');
TempList := TStringList.Create;
for i := l downto 0 do
begin
item := LinksTo(elementbyindex(elementbyindex(elementbyindex(ElementByPath(CurrentReference, 'Items'), i), 0), 0));
if invalidStuff.IndexOf(Signature(item)) >= 0 then
Continue;
edid := EditorID(item);
ItemIndex := Input.IndexOf(edid);
{ Debug } if debugMsg then
addMessage('matlistprinter ' + IntToStr(TempList.Count));
if ItemIndex < 0 then
begin
TempList.Add(edid);
TempList.Add(IntToStr(1));
TempList.Add(IntToStr(1));
TempList.Objects[0] := item;
ItemIndex := Input.addObject(edid, TempList);
end
else
TempList.Assign(Input.Objects[ItemIndex]);
TempList.strings[1] := IntToStr(StrToInt64Def(TempList.strings[1], 0) + 1);
TempList.strings[2] := IntToStr(StrToInt64Def(TempList.strings[2], 0) + StrToInt64Def(GetEditValue(elementbyindex(elementbyindex(elementbyindex(ElementByPath(CurrentReference, 'Items'), i), 0), 1)), 0));
Input.Objects[ItemIndex] := TempList;
end;
RecipeCount := RecipeCount + 1;
end;
end;
limit := 0;
for a := Input.Count - 1 downto 0 do
begin
TempList := Input.Objects[a];
if Length(TempList.strings[1]) = 0 then
begin
Input.Delete[a];
Continue;
end;
if Length(TempList.strings[2]) = 0 then
begin
Input.Delete[a];
Continue;
end;
if StrToInt64Def(TempList.strings[1], 0) < (RecipeCount / 2) then
Input.Delete(a);
if not StrToFloatDef(StrToInt64Def(TempList.strings[1], 0) / StrToInt64Def(TempList.strings[2], 1), 1) > limit then
Continue;
limit := StrToInt64Def(TempList.strings[1], 0) / StrToInt64Def(TempList.strings[2], 1);
LimitIndex := a;
end;
if limit > 0 then
y := 1 / limit
else
y := 1;
for a := Input.Count - 1 downto 0 do
begin
TempList := Input.Objects[a];
if TempList.Count < 0 then
Continue;
item := ObjectToElement(TempList.Objects[0]);
edid := TempList.strings[0];
if StrToInt64Def(TempList.strings[2], 0) > 0 then
amount := StrToFloat(TempList.strings[1]) / StrToFloat(TempList.strings[2])
else
Continue;
if amount = 0.0 then
Continue;
Output.Add('i' + Signature(item) + ':' + GetFileName(GetFile(MasterOrSelf(item))) + '|' + edid + '=' + FloatToStr(amount * y));
end;
if ContainsText('Clothing', CurrentKYWDName) then
begin
if Output.Length < 1 then
begin
Output.Add('iMISC:Skyrim.esm|RuinsLinenPile01=1.0');
end;
end;
Input.Free;
Ini.WriteString('Crafting', CurrentKYWDName, Output.CommaText);
Ini.UpdateFile;
Output.Free;
end;
function IniProcess: integer;
var
TalkToUser: integer;
begin
firstRun := true;
Ini := TMemIniFile.Create(ScriptsPath + 'ALLA.ini');
firstRun := Ini.ReadBool('Defaults', 'UpdateINI', true);
Ini.WriteBool('Defaults', 'UpdateINI', false);
Ini.UpdateFile;
end;
procedure IniBlacklist;
begin
Ini := TMemIniFile.Create(ScriptsPath + 'ALLA.ini');
disWord := TStringList.Create;
if Ini.ReadString('blacklist', 'disallowedWords', '1') = '1' then
begin
disWord.Add('skin');
Ini.WriteString('blacklist', 'disallowedWords', disWord.CommaText);
end
else
disWord.DelimitedText := Ini.ReadString('blacklist', 'disallowedWords', '1');
if Ini.ReadBool('blacklist', 'disallownonplayable', true) then
begin
Ini.WriteBool('blacklist', 'disallownonplayable', true);
disallowNP := Ini.ReadBool('blacklist', 'disallownonplayable', true);
end;
DisKeyword := TStringList.Create;
if Ini.ReadString('blacklist', 'disallowedKeywords', '1') = '1' then
begin
DisKeyword.Add('DisallowEnchanting');
DisKeyword.Add('unique');
DisKeyword.Add('noCraft');
DisKeyword.Add('Dummy');
Ini.WriteString('blacklist', 'disallowedKeywords', DisKeyword.CommaText);
end
else
DisKeyword.DelimitedText := Ini.ReadString('blacklist', 'disallowedKeywords', '1');
if Ini.ReadBool('blacklist', 'ignoreEmpty', true) then
begin
Ini.WriteBool('blacklist', 'ignoreEmpty', true);
ignoreEmpty := Ini.ReadBool('blacklist', 'ignoreEmpty', true);
end;
Ini.UpdateFile;
end;
procedure IniALLASettings;
begin
Ini := TMemIniFile.Create(ScriptsPath + 'ALLA.ini');
defaultOutputPlugin := Ini.ReadString('Defaults', 'OutputPlugin', 'Automated Leveled List Addition.esp');
if not ContainsText(defaultOutputPlugin, '.esp') then
defaultOutputPlugin := defaultOutputPlugin + '.esp';
Ini.WriteString('Defaults', 'OutputPlugin', defaultOutputPlugin);
defaultGenerateEnchantedVersions := Ini.ReadBool('Defaults', 'GenerateEnchanted', false);
Ini.WriteBool('Defaults', 'GenerateEnchanted', defaultGenerateEnchantedVersions);
defaultReplaceInLeveledList := Ini.ReadBool('Defaults', 'ReplaceInLL', true);
Ini.WriteBool('defaults', 'ReplaceInLL', defaultReplaceInLeveledList);
defaultAllowDisenchanting := Ini.ReadBool('Defaults', 'Disenchant', true);
Ini.WriteBool('Defaults', 'Disenchant', defaultAllowDisenchanting);
defaultBreakdownEnchanted := Ini.ReadBool('defaults', 'BreakdownEnchanted', true);
Ini.WriteBool('Defaults', 'BreakdownEnchanted', defaultBreakdownEnchanted);
defaultBreakdownDaedric := Ini.ReadBool('Defaults', 'BreakdownDaedric', true);
Ini.WriteBool('Defaults', 'BreakdownDaedric', defaultBreakdownDaedric);
defaultBreakdownDLC := Ini.ReadBool('Defaults', 'BreakdownDLC', true);
Ini.WriteBool('Defaults', 'BreakdownDLC', defaultBreakdownDLC);
defaultGenerateRecipes := Ini.ReadBool('Defaults', 'GenerateCrafting', true);
Ini.WriteBool('Defaults', 'GenerateCrafting', defaultGenerateRecipes);
defaultChanceBoolean := Ini.ReadBool('Defaults', 'defaultChanceBoolean', true);
Ini.WriteBool('Defaults', 'defaultChanceBoolean', defaultChanceBoolean);
defaultAutoDetect := Ini.ReadBool('Defaults', 'defaultAutoDetect', true);
Ini.WriteBool('Defaults', 'defaultAutoDetect', defaultAutoDetect);
defaultBreakdown := Ini.ReadBool('Defaults', 'defaultBreakdown', true);
Ini.WriteBool('Defaults', 'defaultBreakdown', defaultBreakdown);
defaultOutfitSet := Ini.ReadBool('Defaults', 'defaultOutfitSet', false);
Ini.WriteBool('Defaults', 'defaultOutfitSet', defaultOutfitSet);
defaultCrafting := Ini.ReadBool('Defaults', 'defaultCrafting', true);
Ini.WriteBool('Defaults', 'defaultCrafting', defaultCrafting);
defaultTemper := Ini.ReadBool('Defaults', 'defaultTemper', true);
Ini.WriteBool('Defaults', 'defaultTemper', defaultTemper);
defaultChanceMultiplier := Ini.ReadInteger('Defaults', 'defaultChanceMultiplier', 10);
Ini.WriteInteger('Defaults', 'defaultChanceMultiplier', defaultChanceMultiplier);
defaultEnchMultiplier := Ini.ReadInteger('Defaults', 'defaultEnchMultiplier', 100);
Ini.WriteInteger('Defaults', 'defaultEnchMultiplier', defaultEnchMultiplier);
defaultItemTier01 := Ini.ReadInteger('Defaults', 'defaultItemTier01', 1);
Ini.WriteInteger('Defaults', 'defaultItemTier01', defaultItemTier01);
defaultItemTier02 := Ini.ReadInteger('Defaults', 'defaultItemTier02', 10);
Ini.WriteInteger('Defaults', 'defaultItemTier02', defaultItemTier02);
defaultItemTier03 := Ini.ReadInteger('Defaults', 'defaultItemTier03', 20);
Ini.WriteInteger('Defaults', 'defaultItemTier03', defaultItemTier03);
defaultItemTier04 := Ini.ReadInteger('Defaults', 'defaultItemTier04', 30);
Ini.WriteInteger('Defaults', 'defaultItemTier04', defaultItemTier04);
defaultItemTier05 := Ini.ReadInteger('Defaults', 'defaultItemTier05', 35);
Ini.WriteInteger('Defaults', 'defaultItemTier05', defaultItemTier05);
defaultItemTier06 := Ini.ReadInteger('Defaults', 'defaultItemTier06', 40);
Ini.WriteInteger('Defaults', 'defaultItemTier06', defaultItemTier06);
defaultTemperLight := Ini.ReadInteger('Defaults', 'defaultTemperLight', 1);
Ini.WriteInteger('Defaults', 'defaultTemperLight', defaultTemperLight);
defaultTemperHeavy := Ini.ReadInteger('Defaults', 'defaultTemperHeavy', 2);
Ini.WriteInteger('Defaults', 'defaultTemperHeavy', defaultTemperHeavy);
ProcessTime := Ini.ReadBool('Defaults', 'ProcessTime', false);
Ini.WriteBool('Defaults', 'ProcessTime', ProcessTime);
Constant := Ini.ReadBool('Defaults', 'Constant', true);
Ini.WriteBool('Defaults', 'Constant', Constant);
SetObject('GenerateEnchantedVersions', defaultGenerateEnchantedVersions, slGlobal);
SetObject('ReplaceInLeveledList', defaultReplaceInLeveledList, slGlobal);
SetObject('AllowDisenchanting', defaultAllowDisenchanting, slGlobal);
SetObject('BreakdownEnchanted', defaultBreakdownEnchanted, slGlobal);
SetObject('ChanceMultiplier', defaultChanceMultiplier, slGlobal);
SetObject('BreakdownDaedric', defaultBreakdownDaedric, slGlobal);
SetObject('GenerateRecipes', defaultGenerateRecipes, slGlobal);
SetObject('EnchMultiplier', defaultEnchMultiplier, slGlobal);
SetObject('AddtoLeveledList', defaultAutoDetect, slGlobal);
SetObject('ChanceBoolean', defaultChanceBoolean, slGlobal);
SetObject('BreakdownDLC', defaultBreakdownDLC, slGlobal);
SetObject('TemperLight', defaultTemperLight, slGlobal);
SetObject('TemperHeavy', defaultTemperHeavy, slGlobal);
SetObject('ItemTier01', defaultItemTier01, slGlobal);
SetObject('ItemTier02', defaultItemTier02, slGlobal);
SetObject('ItemTier03', defaultItemTier03, slGlobal);
SetObject('ItemTier04', defaultItemTier04, slGlobal);
SetObject('ItemTier05', defaultItemTier05, slGlobal);
SetObject('ItemTier06', defaultItemTier06, slGlobal);
SetObject('Breakdown', defaultBreakdown, slGlobal);
SetObject('Crafting', defaultCrafting, slGlobal);
SetObject('Temper', defaultTemper, slGlobal);
Ini.UpdateFile;
end;
function IniToMatList: integer;
var
i, t, f, as , MLI : integer;
cs, cg, cf, ce, ca : string;
MaterialsSublist, TempList: TStringList;
item : IInterface;
debugMsg : boolean;
begin
debugMsg := false;
for MLI := MaterialList.Count - 1 downto 0 do
begin
{ debug } if debugMsg then
addMessage('initomatlist (0), keyword: ' + MaterialList[MLI]);
TempList := TStringList.Create;
MaterialsSublist := TStringList.Create;
TempList.DelimitedText := Ini.ReadString('Crafting', MaterialList.strings[MLI], '');
for i := TempList.Count - 1 downto 0 do
begin
cs := TempList.strings[i];
{ debug } if debugMsg then
addMessage('initomatlist (1): ' + cs);
t := Pos(':', cs);
f := Pos('|', cs);
as := Pos('=', cs);
if Copy(cs, 0, 1) = 'i' then
begin
cg := Uppercase(Copy(cs, 2, 4));
cf := Copy(cs, t + 1, f - t - 1);
ce := Copy(cs, f + 1, as - f - 1);
ca := Copy(cs, as + 1, Length(cs) - as);
item := MainRecordByEditorID(GroupBySignature(FileByName(cf), cg), ce);
{ Debug } if debugMsg then
addMessage('IniToMatList (2): ' + cg + ' ' + cf + ' ' + ce + ' ' + ca);
MaterialsSublist.addObject(FloatToStr(ca), item);
{ Debug } // if debugMsg then addMessage('IniToMatList (3): ' + FloatToStr(ca) + ' ' + EditorID(item) + ' ' + EditorID(ObjectToElement(MaterialsSublist.Objects[MaterialsSublist.IndexOf(ca)])));
end
else
if Pos('p', Copy(cs, 0, 1)) = 0 then
begin
cf := Copy(cs, t + 1, f - 1);
ce := Copy(cs, f + 1, Length(cs) - 1);
MaterialsSublist.addObject('Perk', RecordByEDID(FileByName(cf), ce));
{ Debug } if debugMsg then
addMessage('IniToMatList (4): ' + EditorID(item) + ' ' + EditorID(ObjectToElement(MaterialsSublist.Objects[MaterialsSublist.IndexOf(ca)])));
end;
end;
MaterialList.Objects[MLI] := MaterialsSublist;
// MaterialList.Objects[MLI] := TempList;
end;
end;
function MakeCraftable(aRecord, aPlugin: IInterface): IInterface;
var
recipeCraft, recipeCondition, recipeConditions, recipeItem, recipeitems, keywords: IInterface;
amountOfMainComponent, ki, amountOfAdditionalComponent, e : integer;
debugMsg : boolean;
begin
debugMsg := false;
recipeCraft := FindRecipe(false, HashedList, aRecord, aPlugin);
if Assigned(recipeCraft) then
begin
{ Debug } if debugMsg then
addMessage('Recipe Found for: ' + name(aRecord) + ' emptying');
BeginUpdate(recipeCraft);
try
for e := ElementCount(ElementByPath(recipeCraft, 'Items')) - 1 downto 0 do
begin
RemoveByIndex(ElementByPath(recipeCraft, 'Items'), e, false);
end;
for e := ElementCount(ElementByPath(recipeCraft, 'Conditions')) - 1 downto 0 do
begin
RemoveByIndex(ElementByPath(recipeCraft, 'Conditions'), e, false);
end;
finally
EndUpdate(recipeCraft);
end;
end;
if not Assigned(recipeCraft) then
begin
{ Debug } if debugMsg then
addMessage('No Recipe Found for: ' + name(aRecord) + ' Generating new one');
recipeCraft := createRecord(aPlugin, 'COBJ');
// add reference to the created object
SetElementEditValues(recipeCraft, 'CNAM', name(aRecord));
// set Created Object Count
SetElementEditValues(recipeCraft, 'NAM1', '1');
end;
// {Debug} if debugMsg then addMessage('checkpoint');
// recipeCraft := FindCraftingRecipe;
// add required items list
Add(recipeCraft, 'items', true);
// get reference to required items list inside recipe
recipeitems := ElementByPath(recipeCraft, 'items');
// trying to figure out propper requirements amount
if HasKeyword(aRecord, 'ArmorHeavy') then
begin // if it is heavy armor, base the amount of materials on the weight
{ debug } if debugMsg then
addMessage('recipe is for heavy');
amountOfMainComponent := 0;
if Assigned(recipeitems) and Assigned(aRecord) then
amountOfMainComponent := MaterialAmountHeavy(amountOfMainComponent, amountOfAdditionalComponent, recipeitems, aRecord);
amountOfAdditionalComponent := ceil(2);
keywords := ElementByPath(aRecord, 'KWDA');
end
else
if HasKeyword(aRecord, 'ArmorLight') then
begin // Light armor is based on rating
{ debug } if debugMsg then
addMessage('recipe is for light');
amountOfMainComponent := materialAmountLight(amountOfMainComponent, amountOfAdditionalComponent, recipeitems, aRecord);
amountOfAdditionalComponent := floor(amountOfMainComponent / 3);
if amountOfAdditionalComponent < 1 then
amountOfAdditionalComponent := 1;
if amountOfMainComponent < 1 then
amountOfMainComponent := 1;
if amountOfMainComponent > 10 then
amountOfMainComponent := 10;
if amountOfAdditionalComponent > 15 then
amountOfAdditionalComponent := 15;
YggAdditem(recipeitems, getRecordByFormID('000800E4'), amountOfAdditionalComponent); // LeatherStrips
keywords := ElementByPath(aRecord, 'KWDA');
end
else
if HasKeyword(aRecord, 'ArmorClothing') then
begin // clothing
// uses -1.4ln(x/10)+10 for value to get amount
{ Debug } if debugMsg then
addMessage(name(aRecord) + ' is Clothing');
if StrToFloat(GetElementEditValues(aRecord, 'DATA\Value')) < 42 then
begin
amountOfMainComponent := 5;
end
else
if StrToFloat(GetElementEditValues(aRecord, 'DATA\Value')) < 173 then
begin
amountOfMainComponent := 4;
end
else
if StrToFloat(GetElementEditValues(aRecord, 'DATA\Value')) < 730 then
begin
amountOfMainComponent := 3;
end
else
if StrToFloat(GetElementEditValues(aRecord, 'DATA\Value')) < 3020 then
begin
amountOfMainComponent := 2;
end
else
if StrToFloat(GetElementEditValues(aRecord, 'DATA\Value')) > 3020 then
amountOfMainComponent := 1;
// uses -2.5ln(-x+51)+10 for weight to get a second amount and add to first.
if StrToFloat(GetElementEditValues(aRecord, 'DATA\Weight')) >= 50 then
begin
amountOfMainComponent := amountOfMainComponent + 5;
end
else
if StrToFloat(GetElementEditValues(aRecord, 'DATA\Weight')) > 48 then
begin
amountOfMainComponent := amountOfMainComponent + 4;
end
else
if StrToFloat(GetElementEditValues(aRecord, 'DATA\Weight')) > 46 then
begin
amountOfMainComponent := amountOfMainComponent + 3;
end
else
if StrToFloat(GetElementEditValues(aRecord, 'DATA\Weight')) > 40 then
begin
amountOfMainComponent := amountOfMainComponent + 2;
end
else
if StrToFloat(GetElementEditValues(aRecord, 'DATA\Weight')) > 26 then
begin
amountOfMainComponent := amountOfMainComponent + 1;
end
else
amountOfMainComponent := amountOfMainComponent + 0;
amountOfAdditionalComponent := floor(amountOfMainComponent / 3);
if amountOfAdditionalComponent < 1 then
amountOfAdditionalComponent := 1;
if amountOfMainComponent < 1 then
amountOfMainComponent := 1;
end
else
if HasKeyword(aRecord, 'ArmorJewelry') then
begin // jewelry
{ Debug } if debugMsg then
addMessage(name(aRecord) + ' is Jewelry');
if StrToFloat(GetElementEditValues(aRecord, 'DATA\Value')) < 42 then
begin
amountOfMainComponent := 5;
end
else
if StrToFloat(GetElementEditValues(aRecord, 'DATA\Value')) < 173 then
begin
amountOfMainComponent := 4;
end
else
if StrToFloat(GetElementEditValues(aRecord, 'DATA\Value')) < 730 then
begin
amountOfMainComponent := 3;
end
else
if StrToFloat(GetElementEditValues(aRecord, 'DATA\Value')) < 3020 then
begin
amountOfMainComponent := 2;
end
else
if StrToFloat(GetElementEditValues(aRecord, 'DATA\Value')) > 3020 then
amountOfMainComponent := 1;
amountOfAdditionalComponent := floor(StrToFloat(GetElementEditValues(aRecord, 'DATA\Weight')) * 0.2 / 3);
if amountOfAdditionalComponent < 1 then
amountOfAdditionalComponent := 1;
if amountOfMainComponent < 1 then
amountOfMainComponent := 1;
YggAdditem(recipeitems, getRecordByFormID('0005AD9E'), amountOfMainComponent); // gold
keywords := ElementByPath(aRecord, 'KWDA');
end else begin
{ debug } if debugMsg then
addMessage(name(aRecord) + ' is not clothing, jewelry, or armor');
amountOfMainComponent := 3;
amountOfAdditionalComponent := 2;
keywords := ElementByPath(aRecord, 'KWDA');
end;
for ki := 0 to ElementCount(keywords) - 1 do
begin
{ Debug } if debugMsg then
addMessage('makcraftable ' + GetEditValue(elementbyindex(keywords, ki)));
MatByKYWD(EditorID(LinksTo(elementbyindex(keywords, ki))), recipeitems, amountOfMainComponent);
end;
// set EditorID for recipe
if Pos('ARMO', Signature(aRecord)) > 0 then
SetElementEditValues(recipeCraft, 'EDID', 'RecipeArmor' + GetElementEditValues(aRecord, 'EDID'));
if Pos('AMMO', Signature(aRecord)) > 0 then
SetElementEditValues(recipeCraft, 'EDID', 'RecipeAmmo' + GetElementEditValues(aRecord, 'EDID'));
if Pos('WEAP', Signature(aRecord)) > 0 then
SetElementEditValues(recipeCraft, 'EDID', 'RecipeWeapon' + GetElementEditValues(aRecord, 'EDID'));
// add reference to the workbench keyword
Workbench(amountOfMainComponent, amountOfAdditionalComponent, recipeCraft, recipeCondition, recipeConditions, recipeItem, recipeitems, aRecord);
// remove nil record in items requirements, if any
RemoveInvalidEntries(recipeCraft);
if GetElementEditValues(recipeCraft, 'COCT') = '' then
begin
{ Debug } if debugMsg then
addMessage('no item requirements was specified for - ' + name(aRecord));
Remove(recipeCraft);
// YggAdditem(recipeItems, getRecordByFormID('0005AD9E'), 10); // gold
end
else
if not Assigned(ElementByPath(recipeCraft, 'COCT')) then
begin
{ Debug } if debugMsg then
addMessage('no item requirements was specified for - ' + name(aRecord));
Remove(recipeCraft);
// YggAdditem(recipeItems, getRecordByFormID('0005AD9E'), 10); // gold
end
else
if not Assigned(ElementByPath(recipeCraft, 'Items')) then
begin
{ Debug } if debugMsg then
addMessage('no item requirements was specified for - ' + name(aRecord));
Remove(recipeCraft);
// YggAdditem(recipeItems, getRecordByFormID('0005AD9E'), 10); // gold
end
else
if ElementCount(ElementByPath(recipeCraft, 'Items')) < 1 then
begin
{ Debug } if debugMsg then
addMessage('no item requirements was specified for - ' + name(aRecord));
Remove(recipeCraft);
// YggAdditem(recipeItems, getRecordByFormID('0005AD9E'), 10); // gold
end;
end;
function YggcreateRecord(recordSignature: string; plugin: IInterface): IInterface;
var
newRecordGroup: IInterface;
begin
// get category in file
newRecordGroup := GroupBySignature(plugin, recordSignature);
// create record and return it
result := ElementAssign(newRecordGroup, LowInteger, nil, false);
// Result := Add(newRecordGroup, recordSignature, true);
end;
function MaterialAmountHeavy(amountOfMainComponent, amountOfAdditionalComponent: integer; recipeitems, aRecord: IInterface): integer;
var
temp: Double;
begin
temp := StrToFloat(GetElementEditValues(aRecord, 'DATA\Weight'));
if HasKeyword(aRecord, 'ArmorCuirass') then
begin
amountOfMainComponent := floor(temp * 0.3);
if amountOfMainComponent < 10 then
amountOfMainComponent := 10;
if amountOfMainComponent > 15 then
amountOfMainComponent := 15;
amountOfAdditionalComponent := floor(amountOfMainComponent / 5);
if amountOfAdditionalComponent < 1 then
amountOfAdditionalComponent := 1;
if amountOfAdditionalComponent > 3 then
amountOfAdditionalComponent := 3;
YggAdditem(recipeitems, getRecordByFormID('000800E4'), amountOfAdditionalComponent); // LeatherStrips
YggAdditem(recipeitems, getRecordByFormID('0005ACE4'), amountOfAdditionalComponent); // IngotIron
end
else
if HasKeyword(aRecord, 'ArmorBoots') then
begin
amountOfMainComponent := ceil(temp * 0.7);
if amountOfMainComponent < 3 then
amountOfMainComponent := 3;
if amountOfMainComponent > 7 then
amountOfMainComponent := 7;
amountOfAdditionalComponent := floor(amountOfMainComponent / 3);
if amountOfAdditionalComponent < 1 then
amountOfAdditionalComponent := 1;
if amountOfAdditionalComponent > 3 then
amountOfAdditionalComponent := 3;
YggAdditem(recipeitems, getRecordByFormID('000800E4'), amountOfAdditionalComponent); // LeatherStrips
YggAdditem(recipeitems, getRecordByFormID('0005ACE4'), amountOfAdditionalComponent); // IngotIron
end
else
if HasKeyword(aRecord, 'ArmorGauntlets') then
begin
amountOfMainComponent := floor(temp * 0.7);
if amountOfMainComponent < 4 then
amountOfMainComponent := 4;
if amountOfMainComponent > 7 then
amountOfMainComponent := 7;
amountOfAdditionalComponent := floor(amountOfMainComponent / 3);
if amountOfAdditionalComponent < 1 then
amountOfAdditionalComponent := 1;
if amountOfAdditionalComponent > 3 then
amountOfAdditionalComponent := 3;
YggAdditem(recipeitems, getRecordByFormID('000800E4'), amountOfAdditionalComponent); // LeatherStrips
YggAdditem(recipeitems, getRecordByFormID('0005ACE4'), amountOfAdditionalComponent); // IngotIron
end
else
if HasKeyword(aRecord, 'ArmorHelmet') then
begin
amountOfMainComponent := ceil(temp * 0.3);
if amountOfMainComponent < 2 then
amountOfMainComponent := 2;
if amountOfMainComponent > 5 then
amountOfMainComponent := 5;
amountOfAdditionalComponent := floor(amountOfMainComponent / 3);
if amountOfAdditionalComponent < 1 then
amountOfAdditionalComponent := 1;
if amountOfAdditionalComponent > 3 then
amountOfAdditionalComponent := 3;
YggAdditem(recipeitems, getRecordByFormID('000800E4'), amountOfAdditionalComponent); // LeatherStrips
YggAdditem(recipeitems, getRecordByFormID('0005ACE4'), amountOfAdditionalComponent); // IngotIron
end
else
if HasKeyword(aRecord, 'ArmorPants') then
begin
amountOfMainComponent := floor(temp * 0.7);
if amountOfMainComponent < 3 then
amountOfMainComponent := 3;
if amountOfMainComponent > 8 then
amountOfMainComponent := 8;
amountOfAdditionalComponent := floor(amountOfMainComponent / 3);
if amountOfAdditionalComponent < 1 then
amountOfAdditionalComponent := 1;
if amountOfAdditionalComponent > 3 then
amountOfAdditionalComponent := 3;
YggAdditem(recipeitems, getRecordByFormID('000800E4'), amountOfAdditionalComponent); // LeatherStrips
YggAdditem(recipeitems, getRecordByFormID('0005ACE4'), amountOfAdditionalComponent); // IngotIron
end
else
if HasKeyword(aRecord, 'ArmorUnderwear') then
begin
amountOfMainComponent := 1;
end
else
if HasKeyword(aRecord, 'ArmorUnderwearTop') then
begin
amountOfMainComponent := 2;
end
else
if HasKeyword(aRecord, 'ArmorShirt') then
begin
amountOfMainComponent := floor(temp * 0.7);
if amountOfMainComponent < 3 then
amountOfMainComponent := 3;
if amountOfMainComponent > 8 then
amountOfMainComponent := 8;
amountOfAdditionalComponent := floor(amountOfMainComponent / 3);
if amountOfAdditionalComponent < 1 then
amountOfAdditionalComponent := 1;
if amountOfAdditionalComponent > 3 then
amountOfAdditionalComponent := 3;
YggAdditem(recipeitems, getRecordByFormID('000800E4'), amountOfAdditionalComponent); // LeatherStrips
YggAdditem(recipeitems, getRecordByFormID('0005ACE4'), amountOfAdditionalComponent); // IngotIron
end else begin
amountOfMainComponent := ceil(random(5));
if amountOfMainComponent < 1 then
amountOfMainComponent := 1;
if amountOfMainComponent > 5 then
amountOfMainComponent := 5;
amountOfAdditionalComponent := floor(amountOfMainComponent / 3);
if amountOfAdditionalComponent < 1 then
amountOfAdditionalComponent := 1;
if amountOfAdditionalComponent > 3 then
amountOfAdditionalComponent := 3;
YggAdditem(recipeitems, getRecordByFormID('000800E4'), amountOfAdditionalComponent); // LeatherStrips
YggAdditem(recipeitems, getRecordByFormID('0005ACE4'), amountOfAdditionalComponent); // IngotIron
end;
result := amountOfMainComponent;
end;
function materialAmountLight(amountOfMainComponent, amountOfAdditionalComponent: integer; recipeitems, aRecord: IInterface): integer;
var
temp: Double;
begin
temp := StrToFloat(GetElementEditValues(aRecord, 'DATA\Weight'));
if HasKeyword(aRecord, 'ArmorCuirass') then
begin
amountOfMainComponent := floor(temp * 0.3);
if amountOfMainComponent < 10 then
amountOfMainComponent := 10;
if amountOfMainComponent > 15 then
amountOfMainComponent := 15;
amountOfAdditionalComponent := floor(amountOfMainComponent / 5);
if amountOfAdditionalComponent < 1 then
amountOfAdditionalComponent := 1;
if amountOfAdditionalComponent > 3 then
amountOfAdditionalComponent := 3;
YggAdditem(recipeitems, getRecordByFormID('000800E4'), amountOfAdditionalComponent); // LeatherStrips
YggAdditem(recipeitems, getRecordByFormID('0005ACE4'), amountOfAdditionalComponent); // IngotIron
end
else
if HasKeyword(aRecord, 'ArmorBoots') then
begin
amountOfMainComponent := ceil(temp * 0.7);
if amountOfMainComponent < 3 then
amountOfMainComponent := 3;
if amountOfMainComponent > 7 then
amountOfMainComponent := 7;
amountOfAdditionalComponent := floor(amountOfMainComponent / 3);
if amountOfAdditionalComponent < 1 then
amountOfAdditionalComponent := 1;
if amountOfAdditionalComponent > 3 then
amountOfAdditionalComponent := 3;
YggAdditem(recipeitems, getRecordByFormID('000800E4'), amountOfAdditionalComponent); // LeatherStrips
YggAdditem(recipeitems, getRecordByFormID('0005ACE4'), amountOfAdditionalComponent); // IngotIron
end
else
if HasKeyword(aRecord, 'ArmorGauntlets') then
begin
amountOfMainComponent := floor(temp * 0.7);
if amountOfMainComponent < 4 then
amountOfMainComponent := 4;
if amountOfMainComponent > 7 then
amountOfMainComponent := 7;
amountOfAdditionalComponent := floor(amountOfMainComponent / 3);
if amountOfAdditionalComponent < 1 then
amountOfAdditionalComponent := 1;
if amountOfAdditionalComponent > 3 then
amountOfAdditionalComponent := 3;
YggAdditem(recipeitems, getRecordByFormID('000800E4'), amountOfAdditionalComponent); // LeatherStrips
YggAdditem(recipeitems, getRecordByFormID('0005ACE4'), amountOfAdditionalComponent); // IngotIron
end
else
if HasKeyword(aRecord, 'ArmorHelmet') then
begin
amountOfMainComponent := ceil(temp * 0.3);
if amountOfMainComponent < 2 then
amountOfMainComponent := 2;
if amountOfMainComponent > 5 then
amountOfMainComponent := 5;
amountOfAdditionalComponent := floor(amountOfMainComponent / 3);
if amountOfAdditionalComponent < 1 then
amountOfAdditionalComponent := 1;
if amountOfAdditionalComponent > 3 then
amountOfAdditionalComponent := 3;
YggAdditem(recipeitems, getRecordByFormID('000800E4'), amountOfAdditionalComponent); // LeatherStrips
YggAdditem(recipeitems, getRecordByFormID('0005ACE4'), amountOfAdditionalComponent); // IngotIron
end
else
if HasKeyword(aRecord, 'ArmorPants') then
begin
amountOfMainComponent := floor(temp * 0.7);
if amountOfMainComponent < 3 then
amountOfMainComponent := 3;
if amountOfMainComponent > 8 then
amountOfMainComponent := 8;
amountOfAdditionalComponent := floor(amountOfMainComponent / 3);
if amountOfAdditionalComponent < 1 then
amountOfAdditionalComponent := 1;
if amountOfAdditionalComponent > 3 then
amountOfAdditionalComponent := 3;
YggAdditem(recipeitems, getRecordByFormID('000800E4'), amountOfAdditionalComponent); // LeatherStrips
YggAdditem(recipeitems, getRecordByFormID('0005ACE4'), amountOfAdditionalComponent); // IngotIron
end
else
if HasKeyword(aRecord, 'ArmorUnderwear') then
begin
amountOfMainComponent := 1;
end
else
if HasKeyword(aRecord, 'ArmorUnderwearTop') then
begin
amountOfMainComponent := 2;
end
else
if HasKeyword(aRecord, 'ArmorShirt') then
begin
amountOfMainComponent := floor(temp * 0.7);
if amountOfMainComponent < 3 then
amountOfMainComponent := 3;
if amountOfMainComponent > 8 then
amountOfMainComponent := 8;
amountOfAdditionalComponent := floor(amountOfMainComponent / 3);
if amountOfAdditionalComponent < 1 then
amountOfAdditionalComponent := 1;
if amountOfAdditionalComponent > 3 then
amountOfAdditionalComponent := 3;
YggAdditem(recipeitems, getRecordByFormID('000800E4'), amountOfAdditionalComponent); // LeatherStrips
YggAdditem(recipeitems, getRecordByFormID('0005ACE4'), amountOfAdditionalComponent); // IngotIron
end else begin
amountOfMainComponent := ceil(random(5));
if amountOfMainComponent < 1 then
amountOfMainComponent := 1;
if amountOfMainComponent > 5 then
amountOfMainComponent := 5;
amountOfAdditionalComponent := floor(amountOfMainComponent / 3);
if amountOfAdditionalComponent < 1 then
amountOfAdditionalComponent := 1;
if amountOfAdditionalComponent > 3 then
amountOfAdditionalComponent := 3;
YggAdditem(recipeitems, getRecordByFormID('000800E4'), amountOfAdditionalComponent); // LeatherStrips
YggAdditem(recipeitems, getRecordByFormID('0005ACE4'), amountOfAdditionalComponent); // IngotIron
end;
result := amountOfMainComponent;
end;
function FindRecipe(Create: boolean; List: TStringList; aRecord, Patch: IInterface): IInterface;
var
recipeCraft: IInterface;
debugMsg : boolean;
begin
debugMsg := false;
if List.IndexOf(LowerCase(EditorID(WinningOverride(aRecord)))) >= 0 then
begin
result := wbCopyElementToFile(ObjectToElement(List.Objects[List.IndexOf(EditorID(aRecord))]), Patch, false, true);
end else begin
if Create then
begin
recipeCraft := YggcreateRecord('COBJ');
{ Debug } if debugMsg then
addMessage('No Recipe Found');
// add reference to the created object
SetElementEditValues(recipeCraft, 'CNAM', name(aRecord));
// set Created Object Count
SetElementEditValues(recipeCraft, 'NAM1', '1');
result := recipeCraft;
end;
end;
end;
function Workbench(amountOfMainComponent, amountOfAdditionalComponent: integer; recipeCraft, recipeCondition, recipeConditions, recipeItem, recipeitems, aRecord: IInterface): IInterface;
var
debugMsg: boolean;
begin
debugMsg := false;
if Signature(aRecord) = 'ARMO' then
begin
if HasKeyword(aRecord, 'ArmorClothing') then
SetElementEditValues(recipeCraft, 'BNAM', GetEditValue(getRecordByFormID('0007866A'))) // tanning rack for clothing
else
SetElementEditValues(recipeCraft, 'BNAM', GetEditValue(getRecordByFormID('00088105'))); // forge
end;
if Signature(aRecord) = 'AMMO' then
SetElementEditValues(recipeCraft, 'BNAM', GetEditValue(getRecordByFormID('00088108'))); // Sharpening wheel
if Signature(aRecord) = 'WEAP' then
SetElementEditValues(recipeCraft, 'BNAM', GetEditValue(getRecordByFormID('00088105'))); // forge
{ Debug } if debugMsg then
addMessage('Finished Tailoring');
end;
function MatByKYWD(keyword: string; recipeitems: IInterface; amountOfMainComponent: integer): integer;
var
CurrentMaterials: TStringList;
a : integer;
debugMsg : boolean;
begin
debugMsg := false;
if MaterialList.IndexOf(keyword) < 0 then
exit;
{ Debug } if debugMsg then
addMessage('work');
CurrentMaterials := MaterialList.Objects[MaterialList.IndexOf(keyword)];
for a := CurrentMaterials.Count - 1 downto 0 do
begin
{ Debug } if debugMsg then
addMessage('work 2');
if Pos('Perk', CurrentMaterials.strings[a]) > 0 then
begin
{ Debug } if debugMsg then
addMessage('work 3 perk');
// YggAddPerkCondition(recipeitems, ObjectToElement(CurrentMaterials.Objects[a]));
end else begin
{ Debug } if debugMsg then
addMessage('MatByKYWD: ' + name(ObjectToElement(CurrentMaterials.Objects[a])));
YggAdditem(recipeitems, ObjectToElement(CurrentMaterials.Objects[a]), ceil(StrToFloat(CurrentMaterials.strings[a]) * amountOfMainComponent * (random(1) + 0.5)));
end;
tempPerkFunction(keyword, recipeitems, amountOfMainComponent);
end;
end;
function InitializeRecipes: integer;
var
f, r : integer;
BNAM, CurrentFile, CurrentGroup, CurrentItem: IInterface;
StationEDID, temp : string;
debugMsg : boolean;
begin
debugMsg := false;
Recipes := TStringList.Create;
Recipes.Duplicates := dupIgnore;
Recipes.Sorted;
for f := FileCount - 1 downto 0 do
begin
CurrentFile := FileByIndex(f);
if HasGroup(CurrentFile, 'COBJ') then
begin
CurrentGroup := GroupBySignature(CurrentFile, 'COBJ');
for r := ElementCount(CurrentGroup) - 1 downto 0 do
begin
CurrentItem := elementbyindex(CurrentGroup, r);
BNAM := LinksTo(ElementByPath(CurrentItem, 'BNAM'));
temp := LowerCase(EditorID(WinningOverride(LinksTo(ElementByPath(CurrentItem, 'CNAM')))));
StationEDID := LowerCase(EditorID(BNAM));
if IsWinningOVerride(CurrentItem) then
begin
if not(ContainsText(StationEDID, 'armortable')) and not(ContainsText(StationEDID, 'sharpening')) and (ContainsText(StationEDID, 'forge') or (ContainsText(StationEDID, 'skyforge'))) and not(ContainsText(StationEDID, 'cook')) then
begin
Recipes.addObject(temp, CurrentItem);
if debugMsg then
addMessage('adding recipe ' + name(CurrentItem));
end
else
if (StationEDID = 'Smelter') then
begin
Items := ElementByPath(CurrentItem, 'Items');
for i := ElementCount(Items) - 1 downto 0 do
begin
item := WinningOverride(LinksTo(ElementByPath(elementbyindex(Items, i), 'CNTO\Item')));
sigItem := Signature(item);
end;
end;
end;
end;
end else begin
Continue;
end;
end;
HashedList := THashedStringList.Create;
HashedList.Assign(Recipes);
// temper
Recipes := TStringList.Create;
Recipes.Duplicates := dupIgnore;
Recipes.Sorted;
for f := FileCount - 1 downto 0 do
begin
CurrentFile := FileByIndex(f);
if HasGroup(CurrentFile, 'COBJ') then
begin
CurrentGroup := GroupBySignature(CurrentFile, 'COBJ');
for r := ElementCount(CurrentGroup) - 1 downto 0 do
begin
CurrentItem := elementbyindex(CurrentGroup, r);
BNAM := LinksTo(ElementByPath(CurrentItem, 'BNAM'));
temp := LowerCase(EditorID(WinningOverride(LinksTo(ElementByPath(CurrentItem, 'CNAM')))));
StationEDID := LowerCase(EditorID(BNAM));
if IsWinningOVerride(CurrentItem) then
begin
if (ContainsText(StationEDID, 'armortable')) or (ContainsText(StationEDID, 'sharpening')) and not(ContainsText(StationEDID, 'cook')) then
begin
Recipes.addObject(temp, CurrentItem);
if debugMsg then
addMessage('adding recipe ' + name(CurrentItem));
end
else
if (StationEDID = 'Smelter') then
begin
Items := ElementByPath(CurrentItem, 'Items');
for i := ElementCount(Items) - 1 downto 0 do
begin
item := WinningOverride(LinksTo(ElementByPath(elementbyindex(Items, i), 'CNTO\Item')));
sigItem := Signature(item);
end;
end;
end;
end;
end else begin
Continue;
end;
end;
HashedTemperList := THashedStringList.Create;
HashedTemperList.Assign(Recipes);
end;
function tempPerkFunction(keyword: string; recipeitems: IInterface; amountOfMainComponent: integer): integer;
var
CurrentMaterials: IInterface;
a : integer;
begin
if TempPerkListExtra.IndexOf(keyword) < 0 then
exit;
YggAddPerkCondition(recipeitems, ObjectToElement(TempPerkListExtra.Objects[TempPerkListExtra.IndexOf(keyword)]));
end;
procedure tempPerkFunctionSetup;
begin
TempPerkListExtra := TStringList.Create;
TempPerkListExtra.Sorted := true;
TempPerkListExtra.Duplicates := dupIgnore;
TempPerkListExtra.addObject('ArmorMaterialDragonscale', getRecordByFormID('00052190'));
TempPerkListExtra.addObject('ArmorMaterialDragonplate', getRecordByFormID('00052190'));
TempPerkListExtra.addObject('ArmorMaterialDaedric', getRecordByFormID('000CB413'));
TempPerkListExtra.addObject('ArmorMaterialDwarven', getRecordByFormID('000CB40E'));
TempPerkListExtra.addObject('ArmorMaterialEbony', getRecordByFormID('000CB412'));
TempPerkListExtra.addObject('ArmorMaterialElven', getRecordByFormID('000CB40F'));
TempPerkListExtra.addObject('ArmorMaterialElvenGilded', getRecordByFormID('000CB40F'));
TempPerkListExtra.addObject('ArmorMaterialBonemoldHeavy', getRecordByFormID('000CB40D'));
TempPerkListExtra.addObject('DLC2ArmorMaterialBonemoldHeavy', getRecordByFormID('000CB40D'));
TempPerkListExtra.addObject('ArmorMaterialGlass', getRecordByFormID('000CB411'));
TempPerkListExtra.addObject('ArmorMaterialImperialHeavy', getRecordByFormID('000CB40D'));
TempPerkListExtra.addObject('ArmorMaterialOrcish', getRecordByFormID('000CB410'));
TempPerkListExtra.addObject('ArmorMaterialScaled', getRecordByFormID('000CB414'));
TempPerkListExtra.addObject('ArmorMaterialSteel', getRecordByFormID('000CB40D'));
TempPerkListExtra.addObject('ArmorMaterialSteelPlate', getRecordByFormID('000CB414'));
TempPerkListExtra.addObject('ArmorMaterialNordicHeavy', getRecordByFormID('000CB414'));
TempPerkListExtra.addObject('DLC2ArmorMaterialNordicHeavy', getRecordByFormID('000CB414'));
TempPerkListExtra.addObject('ArmorMaterialStalhrimHeavy', getRecordByFormID('000CB412'));
TempPerkListExtra.addObject('DLC2ArmorMaterialStalhrimHeavy', getRecordByFormID('000CB412'));
TempPerkListExtra.addObject('ArmorMaterialStalhrimLight', getRecordByFormID('000CB412'));
TempPerkListExtra.addObject('DLC2ArmorMaterialStalhrimLight', getRecordByFormID('000CB412'));
TempPerkListExtra.addObject('ArmorMaterialBonemoldHeavy2', getRecordByFormID('000CB40D'));
TempPerkListExtra.addObject('ArmorMaterialChitinHeavy', getRecordByFormID('000CB40F'));
TempPerkListExtra.addObject('DLC2ArmorMaterialChitinHeavy', getRecordByFormID('000CB40F'));
TempPerkListExtra.addObject('ArmorMaterialChitinLight', getRecordByFormID('000CB40F'));
TempPerkListExtra.addObject('DLC2ArmorMaterialChitinLight', getRecordByFormID('000CB40F'));
end;
function TrueRecordByEDID(edid: string): IInterface;
var
a : integer;
temp : IInterface;
debugMsg: boolean;
begin
debugMsg := false;
for a := FileCount - 1 downto 0 do
begin
temp := MainRecordByEditorID(GroupBySignature(FileByIndex(a), 'KYWD'), edid);
if Assigned(temp) then
break;
end;
if not Assigned(temp) then
begin
{ Debug } if debugMsg then
addMessage('there is a typo in a edid');
end;
result := temp;
end;
// adds item record reference to the list
function YggAdditem(List: IInterface; item: IInterface; amount: integer): IInterface;
var
newItem : IInterface;
listName: string;
debugMsg: boolean;
begin
debugMsg := false;
// add new item to list
newItem := ElementAssign(List, HighInteger, nil, false);
listName := name(List);
{ debug } if debugMsg then
addMessage('Current COBJ is ' + name(newItem));
if Length(listName) = 0 then
begin
{ debug } if debugMsg then
addMessage('Crafting Recipe doesnt have proper item list');
exit;
end;
// COBJ
if listName = 'Items' then
begin
// set item reference
SetElementEditValues(newItem, 'CNTO - Item\Item', GetEditValue(item));
// set amount
SetElementEditValues(newItem, 'CNTO - Item\Count', amount);
end;
{ debug } if debugMsg then
addMessage('item added');
// remove nil records from list
YggremoveInvalidEntries(List);
result := newItem;
end;
procedure YggremoveInvalidEntries(rec: IInterface);
var
i, num : integer;
lst, ent : IInterface;
recordSignature, refName, countname: string;
begin
recordSignature := Signature(rec);
// containers and constructable objects
if (recordSignature = 'CONT') or (recordSignature = 'COBJ') then
begin
lst := ElementByName(rec, 'Items');
refName := 'CNTO\Item';
countname := 'COCT';
end
num := ElementCount(lst);
// check from the end since removing items will shift indexes
for i := num - 1 downto 0 do
begin
// get individual entry element
ent := elementbyindex(lst, i);
// Check() returns error string if any or empty string if no errors
if Check(ElementByPath(ent, refName)) <> '' then
Remove(ent);
end;
// has counter
if Assigned(countname) then
begin
// update counter subrecord
if num <> ElementCount(lst) then
begin
num := ElementCount(lst);
// set new value or remove subrecord if list is empty (like CK does)
if num > 0 then
SetElementNativeValues(rec, countname, num)
else
RemoveElement(rec, countname);
end;
end;
end;
// adds requirement 'HasPerk' to Conditions list
function YggAddPerkCondition(List: IInterface; perk: IInterface): IInterface;
var
newCondition, tmp: IInterface;
begin
if not(name(List) = 'Conditions') then
begin
if Signature(List) = 'COBJ' then
begin // record itself was provided
tmp := ElementByPath(List, 'Conditions');
if not Assigned(tmp) then
begin
Add(List, 'Conditions', true);
List := ElementByPath(List, 'Conditions');
newCondition := elementbyindex(List, 0); // xEdit will create dummy condition if new list was added
end else begin
List := tmp;
end;
end;
end;
if not Assigned(newCondition) then
begin
// create condition
newCondition := ElementAssign(List, HighInteger, nil, false);
end;
// set type to Equal to
SetElementEditValues(newCondition, 'CTDA\Type', '10000000');
// set some needed properties
SetElementEditValues(newCondition, 'CTDA\Comparison Value', '1');
SetElementEditValues(newCondition, 'CTDA\Function', 'HasPerk');
SetElementEditValues(newCondition, 'CTDA\Perk', GetEditValue(perk));
SetElementEditValues(newCondition, 'CTDA\Run On', 'Subject');
// don't know what is this, but it should be equal to -1, if Function Runs On Subject
SetElementEditValues(newCondition, 'CTDA\Parameter #3', '-1');
// remove nil records from list
RemoveInvalidEntries(List);
result := newCondition;
end;
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment