Created
December 13, 2021 02:40
-
-
Save yggdrasil75/174e8e5d7a638f6aa93ec4866f399040 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //quick add to list. simple solution for reuseability. | |
| procedure AddItemToLVLI(level: integer; item: IInterface; count: integer; List: IInterface); | |
| var | |
| tempRecord: IInterface; | |
| begin | |
| tempRecord := ElementAssign(ElementByPath(currentList, 'Leveled List Entries'), HighInteger, nil, false); | |
| beginUpdate(tempRecord); | |
| try | |
| SetElementEditValues(tempRecord, 'LVLO\Level', level); | |
| SetElementEditValues(tempRecord, 'LVLO\Reference', name(item)); | |
| SetElementEditValues(tempRecord, 'LVLO\Count', count); | |
| finally | |
| endUpdate(tempRecord); | |
| end; | |
| end; | |
| //quick remove from a single list. simple solution for reuseability. | |
| procedure RemoveItemFromLvli(item, List: IInterface); | |
| var | |
| ListItems: IInterface; | |
| ElementIterator: integer; | |
| CurrentItem: IInterface; | |
| begin | |
| ListItems := ElementByPath(List, 'Leveled List Entries'); | |
| beginUpdate(ListItems); | |
| try | |
| for ElementIterator := 0 to ElementCount(ListItems) - 1 do begin | |
| CurrentItem := ElementByIndex(ListItems, ElementIterator); | |
| if equals(LinksTo(ElementByPath(CurrentItem, 'LVLO\Reference')), item) then begin | |
| remove(CurrentItem); | |
| end; | |
| end; | |
| finally | |
| endUpdate(ListItems); | |
| end; | |
| end; | |
| //quick creation of empty lists. | |
| //you need to set Patch as a global IInterface before calling this. patch generally should be the Patch plugin, not the source plugin, but you can technically use the source if you dont care about corruption | |
| function CreateLVLI(name: string): IInterface; | |
| var | |
| newLVLI: IInterface; | |
| begin | |
| newLVLI := Add(Patch, 'LVLI', true); | |
| SetEditorID(newLVLI, name); | |
| result := newLVLI; | |
| end; | |
| //quick creation of empty lists. | |
| //you need to set Patch as a global IInterface before calling this. patch generally should be the Patch plugin, not the source plugin, but you can technically use the source if you dont care about corruption | |
| function CreateLVLIFlagged(name: string; PLevel, Count, Use, Special: Boolean): IInterface; | |
| var | |
| newLVLI: IInterface; | |
| begin | |
| newLVLI := Add(Patch, 'LVLI', true); | |
| beginUpdate(newLVLI); | |
| try | |
| SetEditorID(newLVLI, name); | |
| if PLevel then begin | |
| ElementAssign(ElementByPath(newLVLI, 'LVLF\Calculate from all levels <= player''s level'), HighInteger, nil, false); | |
| end; | |
| if Count then begin | |
| ElementAssign(ElementByPath(newLVLI, 'Calculate for each item in count'), HighInteger, nil, false); | |
| end; | |
| if Use then begin | |
| ElementAssign(ElementByPath(newLVLI, 'Use All'), HighInteger, nil, false); | |
| end; | |
| if Special then begin | |
| ElementAssign(ElementByPath(newLVLI, 'Special Loot'), HighInteger, nil, false); | |
| end; | |
| finally | |
| endUpdate(newLVLI); | |
| end; | |
| result := newLVLI; | |
| end; | |
| //returns stringlist of items in lvli. if full is true then returns a tree with makeup of: | |
| //name | |
| //\item-item object | |
| //\count=count | |
| //\level=level | |
| //if false, then returns list of name-item object. | |
| function LVLIToTString(lvli: IInterface; Full: Boolean): TStringList; | |
| var | |
| i: integer; | |
| ListItems, currentEntry, currentItem: IInterface; | |
| templist, OutList: TStringList; | |
| ALLASublist: IInterface; | |
| begin | |
| listItems := ElementByPath(lvli, 'Leveled List Entries'); | |
| OutList := TStringList.Create; | |
| if Full then begin | |
| for i := 0 to ElementCount(listItems) - 1 do begin | |
| currentEntry := ElementByIndex(listItems, i); | |
| CurrentItem := LinksTo(ElementByPath(currentEntry, 'Reference')); | |
| templist := TStringList.Create; | |
| if Signature(CurrentItem) = 'LVLI' then begin | |
| ALLASublist := CurrentItem; | |
| if ContainsText(EditorID(ALLASublist), 'ALLASublist') then OutList.AddStrings(LVLIToTString(ALLASublist, FULL)); | |
| itemLVLI := LVLIToTString(ALLASublist, Full); | |
| templist.AddObject('nestedLVLI', itemLVLI); | |
| end; | |
| templist.AddObject('item', currentItem); | |
| templist.Add('count='+IntToStr(GetElementEditValue(ElementByPath(currentEntry, 'count')))); | |
| templist.Add('level='+IntToStr(GetElementEditValue(ElementByPath(currentEntry, 'level')))); | |
| OutList.AddObject(EditorID(currentItem), templist); | |
| end; | |
| end else begin | |
| for i := 0 to ElementCount(listItems) - 1 do begin | |
| CurrentItem := LinksTo(ElementByPath(ElementByIndex(listItems, i), 'Reference')); | |
| OutList.AddObject(EditorID(currentItem), currentItem); | |
| end; | |
| end; | |
| result := OutList; | |
| end; | |
| //this takes a list made by LVLIToTString or similar and makes an lvli. | |
| function TStringToLVLI(Name: String; List: TStringList; Full: Boolean): IInterface; | |
| var | |
| LVLI, item: IInterface; | |
| count, level: integer; | |
| begin | |
| LVLI := CreateLVLI(name); | |
| itemcount := list.count; | |
| beginUpdate(LVLI); | |
| try | |
| while itemcount > 200 do begin | |
| for j := 0 to itemcount / 200 do begin | |
| tempList := TStringList.Create; | |
| for i := itemcount - 1 - j * 200 downto 0 do begin | |
| templist.AddObject(list[i], list.objects[i]); | |
| list.remove[i]; | |
| end; | |
| tempLVLI := TStringToLVLI(name + 'ALLASublist' + IntToLetter(j+1), templist, Full); | |
| end; | |
| itemcount := list.count; | |
| AddItemToLVLI(1, tempLVLI, 1, LVLI); | |
| end else begin | |
| if Full then begin | |
| for i := 0 to List.Count - 1 do begin | |
| tempList := List.objects[i]; | |
| count := tempList.values[templist.IndexOf('count')]; | |
| level := templist.values[templist.IndexOf('level')]; | |
| item := ObjectToElement(templist.objects[templist.IndexOf('item')]); | |
| AddItemToLVLI(level, item, count, LVLI); | |
| end; | |
| end else begin | |
| for i := 0 to List.Count - 1 do begin | |
| item := ObjectToElement(List.objects[i]); | |
| AddItemToLVLI(1, item, 1, LVLI); | |
| end; | |
| end; | |
| end; | |
| finally | |
| endUpdate(LVLI); | |
| end; | |
| result := LVLI; | |
| end; | |
| //this is elms function to generate a character based on a number between 1 and 26 (hopefully not 0 and 25…) | |
| function IntToLetter(int: integer): string; | |
| begin | |
| result := Chr(Ord('a') + Pred(int)); | |
| end; | |
| //this actually deletes all items and readds them. it is easier than finding items to remove and adding items that didnt previously exist. | |
| //this also requires a FULL LVLI String List instead of a shrunken. | |
| procedure EditLVLIAsTStringList(LVLI: IInterface; List: TStringList); | |
| var | |
| i: integer; | |
| listItems, CurrentEntry, CurrentItem: IInterface; | |
| templist: TStringList; | |
| count, level: Integer; | |
| item: IInterface; | |
| begin | |
| itemcount := list.count; | |
| //freeze the list | |
| beginUpdate(LVLI); | |
| try | |
| listItems := ElementByPath(lvli, 'Leveled List Entries'); | |
| //this removes all items | |
| for i := 0 to ElementCount(listItems) - 1 do begin | |
| currentEntry := ElementByIndex(listItems, i); | |
| CurrentItem := ElementByPath(currentEntry, 'Reference'); | |
| linkeditem := LinksTo(CurrentItem); | |
| if Signature(linkeditem) = 'LVLI' then begin | |
| if ContainsText(linkeditem, 'ALLASublist') then begin | |
| sublists.addObject(EditorID(linkeditem), linkeditem); | |
| end; | |
| end; | |
| RemoveItemFromLvli(CurrentItem, LVLI); | |
| end; | |
| //this creates sublists for the lists to prevent issues with large lists (this will probably be put into an ini later and pulled from that so it is configurable if you have overloaded lvli issues) | |
| while itemcount > 200 do begin | |
| for j := 0 to itemcount / 200 do begin | |
| tempList := TStringList.Create; | |
| for i := itemcount - 1 - j * 200 downto 0 do begin | |
| templist.AddObject(list[i], ObjectToElement(list.objects[i])); | |
| list.remove[i]; | |
| end; | |
| if sublists.count > 0 then begin | |
| tempLVLI := objectToElement(sublist.objects[0]); | |
| EditLVLIAsTStringList(tempLVLI, templist); | |
| SetEditorID(tempLVLI, name + 'ALLASublist' + IntToLetter(j+1)) | |
| end else | |
| tempLVLI := TStringToLVLI(name + 'ALLASublist' + IntToLetter(j+1), templist, Full); | |
| end; | |
| sublist.delete[0]; | |
| itemcount := list.count; | |
| AddItemToLVLI(1, tempLVLI, 1, LVLI); | |
| end; | |
| //this will add the items back. | |
| for i := 0 to List.Count - 1 do begin | |
| tempList := List.objects[i]; | |
| AddItemToLVLI(templist.values('level'), ObjectToElement(templist.objects[templist.IndexOf('item')]), tempList.values('count'), LVLI); | |
| end; | |
| finally | |
| endUpdate(LVLI); | |
| end; | |
| end; | |
| //quickly generate enchanted version of an armor using a child (is there a better word for it?) version of an enchant. | |
| //relies on ValidENCH and by extension HasKeyword. this is the single item, it doesnt add all variations. | |
| //returns the created item, or the original item (if not valid) | |
| //you need to set Patch as a global IInterface before calling this. patch generally should be the Patch plugin, not the source plugin, but you can technically use the source if you dont care about corruption | |
| //this also doesnt validate that there isnt a copy of this already. use CreateArmoENCHs for full functionality. | |
| //CheckTiers is a way to make sure that the item material value is of the proper tier to accept the enchantments. each tier is 3 enchanments (rank 1, 2, 3 for leather for instance, daedric would be 4, 5, 6. if this is used, then the enchantment must have 6 tiers. | |
| function CreateArmoENCH(item, enchant: IInterface; CheckTiers: Boolean): IInterface; | |
| var | |
| WornRestrict, ResItem, TNAM: IInterface; | |
| FULLName: String; | |
| begin | |
| WornRestrict := ElementByPath(item, 'ENIT\Worn Restrictions'); | |
| if not ValidENCH(item, WornRestrict, CheckTiers) OR not WornRestrict = 'NULL' then begin | |
| result := item; | |
| addMessage('Item is not compatible with Enchantment.'); | |
| exit; | |
| end; | |
| ResItem := wbCopyElementToFile(item, Patch, true, true); | |
| beginUpdate(ResItem); | |
| try | |
| TNAM := ElementByPath(ResItem, 'TNAM') | |
| ElementAssign(TNAM, HighInteger, nil, false); | |
| SetElementEditValues(TNAM, enchant); | |
| FULLName := GetElementEditValues(enchant, 'FULL'); | |
| SetElementEditValues(ResItem, 'FULL', GetElementEditValues(item, 'FULL') + ' of ' + FULLName); | |
| finally | |
| endUpdate(ResItem); | |
| end; | |
| result := ResItem; | |
| end; | |
| //quickly generates enchanted versions of an armor using the base version of an enchant. | |
| //relies on CreateArmoENCH, ValidENCH, HasKeyword. | |
| //this is 6 items (usually) it does not create new enchanments to meet the regular quota of 6, but rather uses the existing ones which have the base as their base. | |
| //returns a stringlist of the created items. | |
| //you need to set Patch as a global IInterface before calling this. patch generally should be the Patch plugin, not the source plugin, but you can technically use the source if you dont care about corruption | |
| function CreateArmoENCHs(item, enchant: IInterface): TStringList; | |
| begin | |
| for i := 0 to ReferencedByCount(enchant) - 1 do begin | |
| CurrentReference := ReferencedByIndex(enchant, i); | |
| if signature(CurrentReference) = 'ENCH' then begin | |
| if equals(LinksTo(ElementByPath(CurrentReference, 'ENIT\Base Enchantment')), enchant) then begin | |
| ENCHList.AddObject(EditorID(CurrentReference), CurrentReference); | |
| end; | |
| end; | |
| end; | |
| if | |
| end; | |
| procedure GenerateAndAddEnchVersion(item, ench: IInterface); | |
| begin | |
| end; | |
| //very simple check for keyword. | |
| function HasKeyword(item: IInterface; aString: string): boolean; | |
| var | |
| tempRecord: IInterface; | |
| i: integer; | |
| begin | |
| result := false; | |
| tempRecord := ElementByPath(item, 'KWDA'); | |
| for i := 0 to ElementCount(tempRecord) - 1 do | |
| begin | |
| if EditorID(LinksTo(elementbyindex(tempRecord, i))) = aString then | |
| begin | |
| result := true; | |
| exit; | |
| end; | |
| end; | |
| end; | |
| //this replaces 1 item in a list with another. this will mostly be used to swap an item with an lvli. | |
| procedure ReplaceItemWithItemLVLI(Original, New, LVLI: IInterface); | |
| begin | |
| ListItems := ElementByPath(LVLI, 'Leveled List Entries'); | |
| beginUpdate(ListItems); | |
| try | |
| for ElementIterator := 0 to ElementCount(ListItems) - 1 do begin | |
| CurrentItem := ElementByIndex(ListItems, ElementIterator); | |
| CurrentSpecific := ElementByPath(CurrentItem, 'LVLO\Reference'); | |
| if equals(LinksTo(CurrentSpecific), Original) then begin | |
| SetEditValue(CurrentSpecific, New); | |
| end; | |
| end; | |
| finally | |
| endUpdate(ListItems); | |
| end; | |
| end; | |
| //checks if the "worn restrictions" keyword list is in the item that an enchantment is being added to. for use with CreateArmoENCH and CreateWeapENCH. requires HasKeyword | |
| //CheckTiers is a way to make sure that the item material value is of the proper tier to accept the enchantments. | |
| //each tier is 3 enchanments (rank 1, 2, 3 for leather for instance, daedric would be 4, 5, 6. | |
| //tiers use the ini file to determine which ranks they use. | |
| function ValidENCH(item, FLST: IInterface; CheckTiers: Boolean): boolean; | |
| var | |
| list, CurrentKeyword: IInterface; | |
| ElementIterator: integer; | |
| probresult: boolean; | |
| begin | |
| result := false; | |
| list := ElementByPath(FLST, 'FormIDs'); | |
| for ElementIterator := 0 to elementCount(list) - 1 do begin | |
| CurrentKeyword := EditorID(LinksTo(ElementByIndex(list, ElementIterator))); | |
| if hasKeyword(item, CurrentKeyword) then begin | |
| probresult := true; //dont want to set result too early and find the next section kills it. so setting "probable result" here. | |
| exit; | |
| end; | |
| end; | |
| if CheckTiers then begin | |
| Ini := TMemIniFile.Create('YGGAutomation.ini'); | |
| end; | |
| end; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment