Claire
2 years ago
2 changed files with 160 additions and 2 deletions
@ -0,0 +1,150 @@ |
|||||||
|
{ |
||||||
|
Dump book text |
||||||
|
Dumps "book text" property of every book in loaded plugins |
||||||
|
|
||||||
|
Source for most copypasta: |
||||||
|
https://github.com/AngryAndConflict/skyrim-utils/ |
||||||
|
|
||||||
|
Revisions by Pragasette: |
||||||
|
https://stackoverflow.com/questions/70357811/pascal-scripting-for-xedit-how-do-i-check-whether-a-substring-is-present-in-a/70361312#70361312 |
||||||
|
} |
||||||
|
unit UserScript; |
||||||
|
|
||||||
|
interface |
||||||
|
|
||||||
|
const |
||||||
|
// change this to False to actually write the text files |
||||||
|
DRY_RUN = False; |
||||||
|
// change this to False if you want to continue after the first error |
||||||
|
STOP_ON_ERROR = True; |
||||||
|
|
||||||
|
implementation |
||||||
|
|
||||||
|
uses |
||||||
|
xEditAPI; |
||||||
|
|
||||||
|
// check if rec editor ID contains any string in blacklist |
||||||
|
function IsBlacklisted(rec: IwbMainRecord; blacklist: TStringList): Boolean; |
||||||
|
var |
||||||
|
i: Cardinal; |
||||||
|
edid: string; |
||||||
|
//needle, haystack: string; |
||||||
|
begin |
||||||
|
Result := False; |
||||||
|
edid := EditorID(rec); |
||||||
|
|
||||||
|
for i := 0 to Pred(blacklist.Count) do |
||||||
|
begin |
||||||
|
//needle := blacklist[i]; |
||||||
|
//haystack := edid; |
||||||
|
//AddMessage('====' + edid + '===='); |
||||||
|
//AddMessage('looking in ' + haystack); |
||||||
|
//AddMessage(#9 + ' for ' + needle + '...'); |
||||||
|
//AddMessage(' test: ' + IntToStr(Pos(needle, haystack)); |
||||||
|
|
||||||
|
if (Pos(blacklist[i], edid) > 0) then |
||||||
|
begin |
||||||
|
Result := True; |
||||||
|
AddMessage('Skipping: ' + edid); |
||||||
|
Break; |
||||||
|
end; |
||||||
|
end; |
||||||
|
end; |
||||||
|
|
||||||
|
function Initialize: Integer; |
||||||
|
var |
||||||
|
i, j: Cardinal; |
||||||
|
f: IwbFile; |
||||||
|
bookGroup: IwbGroupRecord; |
||||||
|
book: IwbMainRecord; |
||||||
|
btext, outputPath, fname: string; |
||||||
|
blacklist, output: TStringList; |
||||||
|
begin |
||||||
|
Result := 0; |
||||||
|
outputPath := ProgramPath + 'Output\'; |
||||||
|
|
||||||
|
if not DRY_RUN then |
||||||
|
begin |
||||||
|
CreateDir(outputPath); |
||||||
|
end; |
||||||
|
|
||||||
|
blacklist := TStringList.Create; |
||||||
|
|
||||||
|
try |
||||||
|
// match editor IDs containing any of following |
||||||
|
blacklist.Add('DLC1ElderScroll'); |
||||||
|
blacklist.Add('DLC1FVBook01Falmer'); |
||||||
|
blacklist.Add('DLC1FVBook02Falmer'); |
||||||
|
blacklist.Add('DLC1FVBook03Falmer'); |
||||||
|
blacklist.Add('DLC1FVBook04Falmer'); |
||||||
|
blacklist.Add('DLC2BlackBook'); |
||||||
|
blacklist.Add('DA04ElderScroll'); |
||||||
|
blacklist.Add('ExpSpiderCrftBook'); |
||||||
|
blacklist.Add('QA'); |
||||||
|
blacklist.Add('Recipe'); |
||||||
|
blacklist.Add('SpellTome'); |
||||||
|
|
||||||
|
AddMessage('Dumping books...'); |
||||||
|
|
||||||
|
for i := 0 to Pred(FileCount) do |
||||||
|
begin |
||||||
|
f := FileByIndex(i); |
||||||
|
bookGroup := GroupBySignature(f, 'BOOK'); |
||||||
|
|
||||||
|
for j := 0 to Pred(ElementCount(bookGroup)) do |
||||||
|
begin |
||||||
|
book := ElementByIndex(bookGroup, j); |
||||||
|
|
||||||
|
if IsMaster(book) then |
||||||
|
begin |
||||||
|
book := WinningOverride(book); |
||||||
|
|
||||||
|
// if it's not blacklisted, do things |
||||||
|
if (not IsBlacklisted(book, blacklist)) then |
||||||
|
begin |
||||||
|
// this it the raw text content of each BOOK's DESC attribute |
||||||
|
btext := GetElementEditValues(book, 'DESC'); |
||||||
|
|
||||||
|
if (Length(btext) > 0) then |
||||||
|
begin |
||||||
|
fname := outputPath + GetElementEditValues(book, 'EDID') + '.txt'; |
||||||
|
AddMessage('Outputting to: ' + fname); |
||||||
|
|
||||||
|
if not DRY_RUN then |
||||||
|
begin |
||||||
|
output := TStringList.Create; |
||||||
|
|
||||||
|
try |
||||||
|
try |
||||||
|
output.Add(btext); |
||||||
|
output.SaveToFile(fname); |
||||||
|
//AddMessage('Successfully saved!'); |
||||||
|
//AddMessage(#9 + fname); |
||||||
|
//AddMessage(#20); |
||||||
|
except |
||||||
|
AddMessage('===ERROR=== Unable to save ' + fname + '!'); |
||||||
|
|
||||||
|
if STOP_ON_ERROR then |
||||||
|
begin |
||||||
|
raise; |
||||||
|
end; |
||||||
|
end; |
||||||
|
finally |
||||||
|
output.Free; |
||||||
|
end; |
||||||
|
end; |
||||||
|
end; |
||||||
|
end; |
||||||
|
end; |
||||||
|
|
||||||
|
//AddMessage('----------') |
||||||
|
end; |
||||||
|
end; |
||||||
|
|
||||||
|
//AddMessage(btext) |
||||||
|
finally |
||||||
|
blacklist.Free; |
||||||
|
end; |
||||||
|
end; |
||||||
|
|
||||||
|
end. |
@ -1,3 +1,11 @@ |
|||||||
# SSEEdit-BookDumper |
# SSEEdit Book Dumper |
||||||
|
|
||||||
Pascal script for SSEEdit, which dumps the text content of every book object in every loaded plugin and master file. |
Pascal script for SSEEdit, which dumps the text content of every book object in every loaded plugin and master file. |
||||||
|
|
||||||
|
## What is this for? |
||||||
|
|
||||||
|
I wanted to make grammar and spelling corrections to all of Skyrim's vanilla books, and I needed a way to extract every book's text property in an easy-to-handle format. |
||||||
|
|
||||||
|
This script finds all book objects in every file loaded into SSEEdit, and it dumps the content of each book into an individual text file. |
||||||
|
|
||||||
|
At some point, I'll be modifying this script to import my text file edits back into SSEEdit. |
Loading…
issues.context.reference_issue