NOT A TUTORIAL! If you don't already know how these things works, nevermind this
Needed:
tes3cmd v0.40 pre-release-2 (use v0.37 if you need the modify function)
Windows assumed for the following command lines: del
Windows: watch out for 2047/8191 characters command line limit, special characters in .bat files
Notepad++ suggested for quick editing of text and .bat files:
1 Exteriors
2 Interiors
3 Cell objects
4 Non-cell objects
5 Scripts
6 Dialogue
7 Merge
8 Remove from the original file
Color code:
Give those filenames to make copying commands easy
These lines can be blindly copy-pasted, with these text outputs that need attention or editing
These things need your input *
* Warning: for the delete or dump function, you may need to cut lists to a length under the command line character limit. Using regex | instead of new arguments helps reduce the character count.
* Warning: the characters [\^$.|?*+() are all special in some regex arguments like --id, --match... precede any of them by \ first. Exteriors or temporary interior cell names could contain these characters, and for them all parentheses must be \( and \)
0 CLEANING & ANALYSIS
Copying the complete section file into TR_SectionFile.ESP
Before cleaning, turn the latest TR_Mainland and Data add-on into ESMs and make the section dependent on them, so tes3cmd can find all dirty objects.
Cleaning:
tes3cmd clean TR_SectionFile.ESP
tes3cmd dump --exterior TR_SectionFile.ESP > TR_SectionFileExt.txt
and look for any remaining junk cells at the end
Section object IDs must start with "TR_" and this is later used to trim down data, but that doesn't mean there aren't bad IDs in the section.
Finding bad IDs:
tes3cmd dump --list --type GLOB --type SCPT --type BODY --type ENCH --type SNDG --type STAT --type WEAP --type NPC_ --type CREA --type LEVC --type SPEL --type ALCH --type LEVI --type ACTI --type APPA --type ARMO --type BOOK --type CLOT --type CONT --type DOOR --type INGR --type LIGH --type LOCK --type MISC --type PROB --type REPA --id "(?!^TR_.*$)^.+" TR_SectionFile.ESP > TR_Section_BadIDs.txt
Any results must be dealt with first.
Additional warning: any weird characters that aren't supported by your .bat text editor, command line, tes3cmd... will make trouble. Usually they'll have created issues in the CS or scripts before, but if not, see how to detect them: - or they'll net you error messages sooner or later.
Before cutting anything, you need to know all quests in the section
tes3cmd dump --match "DATA: JournalIndex:" TR_SectionFile.ESP > TR_SectionQuests.txt
and map out their locations, because you don't want to do all this and find the areas you chose are interdependent.
You also need to know if anything odd is going on with unlinked interiors. If not, see 2a
1 EXTERIORS
Check that the cleaned file is renamed TR_SectionFile.ESP (not "Clean TR_SectionFile.ESP")
Cutting temporary exteriors from TR_SectionFile.ESP into TR_Cut_Ext.ESP with
- tesame (keeping their PGRD, LAND and all LTEX = land Textures) or cutting tool,
- or tes3cmd:
exporting WITHOUT LTEX for now because it's enough to scan interiors: LTEX will be included after finishing the list of interior cells.
tes3cmd dump --exterior --list TR_SectionFile.ESP > TR_Cut_Ext.txt
clean into list of \(X, Y\) coordinates, add each into --id "\(X, Y\)" and concatenate
tes3cmd dump --exterior --id "each exterior cell" --raw-with-header "TR_Cut_Ext.ESP" TR_SectionFile.ESP
2a UNLINKED INTERIORS
Isolated interiors that aren't linked to anything:
tes3cmd dump --interior --list --no-match "DODT:" TR_SectionFile.ESP > TR_SectionCellsUnlinked.txt
Unlinked doors: see bat file, same as below example but it checks all door IDs
IDs containing "door"... in the exterior that aren't linked doors:
tes3cmd dump --exterior --instance-match "door" --raw-with-header "TR_Cut_Ext_Doors.ESP" TR_Cut_Ext.ESP
(this is a hacky match search, so you may want to delete instances like "doorframe" or "doorgrate" here)
tes3cmd dump --instance-no-match "Destination:" TR_Cut_Ext_Doors.ESP > TR_Cut_Ext_DoorsUnlinked.txt
Note that empty interiors may be dummy cells for dialogue conditions.
This example leaves out doors that don't contain "door" in the ID (list more IDs with |)
Leaves out any interiors linked to themselves or other interiors only. If you're clueless to whether there could be interiors that are by design only accessible by scripts in the section, that can be checked:
2b INTERIORS
Interiors linked in the exterior:
tes3cmd dump --instance-match "Destination:" --raw-with-header "TR_Cut_Int1.ESP" TR_Cut_Ext.ESP
tes3cmd delete --sub-no-match "Destination:" TR_Cut_Int1.ESP
tes3cmd dump TR_Cut_Int1.ESP > TR_Cut_Int1.txt
del "TR_Cut_Int1.ESP"
del "TR_Cut_Int1~1.ESP"
clean into list of names,
add any unlinked interiors if found needed,
remember to add \ before any parentheses \( \) or special regex characters
add each into --exact-id "" and concatenate
tes3cmd dump --interior --exact-id "each interior cell" --raw-with-header "TR_Cut_Int1.ESP" TR_SectionFile.ESP
Interiors level 2:
Interiors level 3...
Interiors level 4...
Repeat until redundant.
Cut exteriors again together with their interiors into TR_Cut_Cells.ESP:
- tesame (remember to include all LTEX)
- or tes3cmd:
Concatenating all --id exterior and --exact-id interior lists from
TR_Cut_Ext.txt
TR_Cut_Int1.txt, TR_Cut_Int2.txt...
but here put them into one single --id regex, so that LTEX can first be included.
All cell names with parentheses (see special regex characters) must have parentheses replaced by \( and \)
All exteriors (X, Y) and all interiors need to be concatenated with | between them, like this
--id "(?!.*(\(X, Y\)|\(X, Y\)|interior|interior).*$)^.+"
tes3cmd dump --type CELL --type PGRD --type LAND --type LTEX --raw-with-header "TR_Cut_Cells.ESP" TR_SectionFile.ESP
tes3cmd delete --type CELL --type PGRD --type LAND --id "(?!.*(all cells).*$)^.+" "TR_Cut_Cells.ESP"
Remove the same from the section file:
tes3cmd delete --type CELL --type PGRD --type LAND --id "(?!.*(all cells).*$)^.+" TR_SectionFile.ESP
final cut:
TR_Cut_Cells.ESP
3 CELL OBJECTS
tes3cmd dump --instance-match "TR_" --raw-with-header "TR_Cut_CellObjects.ESP" TR_Cut_Cells.ESP
tes3cmd delete --sub-no-match "Name:TR_" TR_Cut_CellObjects.ESP
tes3cmd dump TR_Cut_CellObjects.ESP > TR_Cut_CellObjects.txt
del "TR_Cut_CellObjects.ESP"
del "TR_Cut_CellObjects~1.ESP"
clean into list of names, add each into --exact-id "" and concatenate
yes there are cell names: that's why we'll delete CELL type afterwards. The second line after each "Record:" is by default the cell name (and some objects are also pushed into this position by the --sub-no-match operation)
there can still be some object IDs from Data (guard NPCs), it doesn't matter if you don't remove them because unless the section file is dirty it doesn't have them
tes3cmd dump --exact-id "each cell object" --raw-with-header "TR_Cut_CellObjects.ESP" TR_SectionFile.ESP
tes3cmd delete --type CELL TR_Cut_CellObjects.ESP
del "TR_Cut_CellObjects~1.ESP"
Now finding any objects contained by cell objects:
tes3cmd dump --type CONT --type NPC_ --type CREA --type WEAP --type ARMO --type CLOT --raw-with-header "TR_Cut_CellObjectsContained.ESP" TR_Cut_CellObjects.ESP
tes3cmd delete --sub-no-match "Object:TR_" TR_Cut_CellObjectsContained.ESP
tes3cmd delete --sub-no-match "Spell:TR_" TR_Cut_CellObjectsContained~1.ESP
tes3cmd delete --sub-no-match "Enchanting:TR_" TR_Cut_CellObjectsContained~2.ESP
tes3cmd dump TR_Cut_CellObjectsContained.ESP > TR_Cut_CellObjectsContained.txt
tes3cmd dump TR_Cut_CellObjectsContained~1.ESP > TR_Cut_CellObjectsSpells.txt
tes3cmd dump TR_Cut_CellObjectsContained~2.ESP > TR_Cut_CellObjectsEnchant.txt
del TR_Cut_CellObjectsContained.ESP
del TR_Cut_CellObjectsContained~1.ESP
del TR_Cut_CellObjectsContained~2.ESP
del TR_Cut_CellObjectsContained~3.ESP
verify that the 3 text outputs are empty, if not add to TR_Cut_CellObjects.txt and dump again,
If necessary re-run contained enchantments:
4 NON-CELL OBJECTS
Making a complete dump of instanceable objects in the file and removing the cell objects already found:
tes3cmd dump --type STAT --type WEAP --type NPC_ --type CREA --type LEVC --type SPEL --type ALCH --type LEVI --type ACTI --type APPA --type ARMO --type BOOK --type CLOT --type CONT --type DOOR --type INGR --type LIGH --type LOCK --type MISC --type PROB --type REPA --raw-with-header "TR_SectionObjectsNoInstance.ESP" TR_SectionFile.ESP
tes3cmd delete --exact-id "each cell object" TR_SectionObjectsNoInstance.ESP
del "TR_SectionObjectsNoInstance~1.ESP"
Small digression: let's first find if any NPCs from the remaining section had ownerships in the cut:
tes3cmd dump --type NPC_ --list TR_SectionObjectsNoInstance.ESP > TR_SectionRemainingNPCs.txt
clean into list of names, add each into --no-match "Owner_Actor:" and concatenate
tes3cmd dump --type CELL --type PGRD --type LAND --raw-with-header "TR_Cut_CellObjectOwners.ESP" TR_Cut_Cells.ESP
tes3cmd delete --sub-no-match "Owner_Actor:each npc" TR_Cut_CellObjectOwners.ESP
tes3cmd dump TR_Cut_CellObjectOwners.ESP > TR_Cut_CellObjectOwners.txt
del "TR_Cut_CellObjectOwners.ESP"
del "TR_Cut_CellObjectOwners~1.ESP"
if the result is not empty, deal with it (add NPCs to the cut list, or change ownerships in TR_Cut_Cells.ESP using tes3cmd v0.37 modify --sub-match "Owner" --replace "///")
Cut cells having already been removed from the section (2b),
repeating all cell object operations on the cells remaining in the section:
tes3cmd dump --type CELL --type PGRD --type LAND --raw-with-header "TR_SectionRemainingCells.ESP" TR_SectionFile.ESP
tes3cmd dump --instance-match "TR_" --raw-with-header "TR_SectionRemainingCellObjects.ESP" TR_SectionRemainingCells.ESP
tes3cmd delete --sub-no-match "Name:TR_" TR_SectionRemainingCellObjects.ESP
tes3cmd dump TR_SectionRemainingCellObjects.ESP > TR_SectionRemainingCellObjects.txt
del "TR_SectionRemainingCellObjects.ESP"
del "TR_SectionRemainingCellObjects~1.ESP"
cleaning the SectionRemainingCellObjects text output into a clean list of IDs as before,
*take notice if the list is more than ... lines (see command line character limits)
tes3cmd dump --exact-id "each object from SectionRemainingCellObjects" --raw-with-header "TR_SectionRemainingCellObjects.ESP" TR_SectionFile.ESP
tes3cmd delete --type CELL TR_Cut_CellObjects.ESP
tes3cmd dump --type CONT --type NPC_ --type CREA --type WEAP --type ARMO --type CLOT --raw-with-header "TR_SectionRemainingCellObjectsContained.ESP" TR_SectionRemainingCellObjects.ESP
tes3cmd delete --sub-no-match "Object:TR_" TR_SectionRemainingCellObjectsContained.ESP
tes3cmd delete --sub-no-match "Spell:TR_" TR_SectionRemainingCellObjectsContained~1.ESP
tes3cmd dump TR_SectionRemainingCellObjectsContained.ESP > TR_SectionRemainingCellObjectsContained.txt
tes3cmd dump TR_SectionRemainingCellObjectsContained~1.ESP > TR_SectionRemainingCellObjectsSpells.txt
del TR_SectionRemainingCellObjectsContained.ESP
del TR_SectionRemainingCellObjectsContained~1.ESP
del TR_SectionRemainingCellObjectsContained~2.ESP
verify that the contained objects/spells text outputs are empty,
if not add to TR_SectionRemainingCellObjects.txt
*if the list is more than ... lines or characters (see command line character limits), repeat the next "delete" line with smaller chunks
tes3cmd delete --exact-id "each object from SectionRemainingCellObjects" TR_SectionObjectsNoInstance.ESP
tes3cmd dump --list --type NPC_ TR_SectionObjectsNoInstance.ESP > TR_SectionNPCsNoInstance.txt
tes3cmd delete --type NPC_ TR_SectionObjectsNoInstance.ESP
tes3cmd dump --list TR_SectionObjectsNoInstance.ESP > TR_SectionObjectsNoInstance.txt
del "TR_SectionObjectsNoInstance.ESP"
del "TR_SectionObjectsNoInstance~1.ESP"
del "TR_SectionObjectsNoInstance~2.ESP"
all objects without instances (not placed in cells) are now in TR_SectionObjectsNoInstance.txt
investigate.
looking up any uses of all 0-instance objects:
if any need to be into the part of the section you're cutting, add to TR_Cut_CellObjects.txt and repeat part 3 from tes3cmd dump --exact-id "each cell object" onwards.
From now on TR_Cut_CellObjects.ESP contains all cell and non-cell objects.
5 SCRIPTS
Local scripts:
tes3cmd dump TR_Cut_CellObjects.ESP > TR_CellObjectScripts.txt
delete non-SCRI lines
optional: remove duplicate lines
add into --exact-id "" and concatenate into TR_Cut_CellObjects.txt
Non-local scripts:
tes3cmd dump --type DIAL --type INFO --type SCPT --raw-with-header "TR_SectionDialogueAndScripts.ESP" TR_SectionFile.ESP
tes3cmd dump "TR_SectionDialogueAndScripts.ESP" > TR_SectionDialogueAndScripts.txt
look up any uses of "StartScript"
investigate
If anything needs to be in what you're cutting, add into TR_Cut_CellObjects.txt
Global variables and sounds:
tes3cmd dump --list --type GLOB --type SOUN TR_SectionFile.ESP > TR_SectionGlobalVars.txt
investigate each
if there are many, see "looking up any uses of all 0-instance objects:" for the quick way
if appropriate add into TR_Cut_CellObjects.txt
tes3cmd dump --exact-id "each script" --exact-id "each object" --raw-with-header "TR_Cut_Objects.ESP" TR_SectionFile.ESP
Before removing the same from the section file,
find any custom objects that might be used in both parts: replace --exact-id with --sub-no-match
tes3cmd dump --type CELL --type PGRD --type LAND --raw-with-header "TR_SectionRemainingCells.ESP" TR_SectionFile.ESP
tes3cmd dump --instance-match "TR_" --raw-with-header "TR_SectionRemainingCellObjects.ESP" TR_SectionRemainingCells.ESP
tes3cmd delete --sub-no-match "Name:TR_" --sub-no-match "each object" TR_SectionRemainingCellObjects.ESP
tes3cmd dump TR_SectionRemainingCellObjects.ESP > TR_SectionSharedObjects.txt
del "TR_SectionRemainingCellObjects.ESP"
del "TR_SectionRemainingCellObjects~1.ESP"
deal with any results manually (ownerships: just change them in TR_SectionFile.ESP using tes3cmd v0.37 modify --replace "///")
or remove them from the delete list.
Removing the same from the section file:
*if the list is more than 500 lines see the Warning for delete; repeat the next "delete" line with smaller chunks
tes3cmd delete --exact-id "each script" --exact-id "each object" TR_SectionFile.ESP
Final cut:
TR_Cut_Objects.ESP
6 DIALOGUE
Raw dump:
tes3cmd dump --type DIAL --type INFO --raw-with-header "TR_Cut_Dialogue.esp" TR_SectionFile.ESP
The rest can not be automated,
but dumps can still be used for reference.
First: journals,
If not sure yet keep/export them all and sort them out later, they'll always be first in the list (tes3cmd dump or TESAME) and will need to be loaded first.
Then: dialogue,
What you cannot do is filter dialogue for only known cells and NPC IDs and call it a day, because there can still be lines with conditions like local variables or Class instead. What you CAN do is first filter for any dialogue that has no cell or ID conditions, then work with that.
7 MERGE
Like for any other section merges, turn TR_Mainland.esp into an ESM and load it.
Load in the CS imperatively in this order:
- Any special objects if they were cut in TESAME instead of being added to the tes3cmd lists (GLOBal variables, SOUNds...)
- TR_Cut_Objects.ESP
- TR_Cut_Cells.ESP
- all Journals if separate
- TR_Cut_Dialogue.ESP or all dialogue
Recompile scripts, Combine loaded ESPs into the new section cut, remove TR_Mainland.ESM dependence
Optional routine Error Check Results (errors are normal for implicit local variables in operations or conditions)
Test load each new file ingame, separately, on vanilla engine.
8 REMOVAL
Cells and objects: removed with tes3cmd at the end of 2b and 5
Dialogue:
To generally delete dialogue content with TESAME or tes3cmd is bad (unless: cleaning a dirty line, removing a whole topic, or you know exactly what you're doing and know that list ordering data won't be lost).
Summary:
when to use the CS: merging files, deleting dialogue lines
when to use TESAME: optionally for cutting cells or cutting 100% of dialogue (all DIAL+INFO)
when to use tes3cmd: everything else