Full Code of matortheeternal/smash for AI

master 60c8b34bced6 cached
708 files
17.0 MB
4.5M tokens
1 requests
Copy disabled (too large) Download .txt
Showing preview only (17,908K chars total). Download the full file to get everything.
Repository: matortheeternal/smash
Branch: master
Commit: 60c8b34bced6
Files: 708
Total size: 17.0 MB

Directory structure:
gitextract_wihtrx14/

├── .gitignore
├── ESPs/
│   ├── SmashTestPlugin01.esp
│   ├── SmashTestPlugin02.esp
│   └── SmashTestPlugin03.esp
├── LICENSE.txt
├── README.md
├── design/
│   ├── code snippets/
│   │   ├── GetMasterElement.pas
│   │   ├── Mator Smash v0.9.pas
│   │   └── better build algorithm.pas
│   ├── diagrams/
│   │   └── Mator Smash.vpp
│   └── notes/
│       ├── algorithm problems.txt
│       ├── handling.txt
│       ├── high level design.txt
│       ├── linking explanation.txt
│       └── todos 1024.txt
├── frontend/
│   ├── MatorSmash.dpr
│   ├── MatorSmash.dproj
│   ├── MatorSmash.mes
│   ├── MatorSmash.res
│   ├── ModelSupport_MatorSmash/
│   │   ├── MatorSmash/
│   │   │   └── default.txvpck
│   │   ├── default.txvpck
│   │   ├── msEditForm/
│   │   │   └── default.txvpck
│   │   ├── msFrontend/
│   │   │   └── default.txvpck
│   │   ├── msOptionsForm/
│   │   │   └── default.txvpck
│   │   ├── msProfileForm/
│   │   │   └── default.txvpck
│   │   ├── msProfilePanel/
│   │   │   └── default.txvpck
│   │   ├── msSmashForm/
│   │   │   └── default.txvpck
│   │   ├── msSplashForm/
│   │   │   └── default.txvpck
│   │   └── msThreads/
│   │       └── default.txvpck
│   ├── lang/
│   │   └── english.lang
│   ├── msAlgorithm.pas
│   ├── msChoicePanel.pas
│   ├── msConfiguration.pas
│   ├── msConflict.pas
│   ├── msConflictForm.dfm
│   ├── msConflictForm.pas
│   ├── msCore.pas
│   ├── msEditForm.dfm
│   ├── msEditForm.pas
│   ├── msLoader.pas
│   ├── msOptionsForm.dfm
│   ├── msOptionsForm.pas
│   ├── msPluginSelectionForm.dfm
│   ├── msPluginSelectionForm.pas
│   ├── msPriorityForm.dfm
│   ├── msPriorityForm.pas
│   ├── msProfileForm.dfm
│   ├── msProfileForm.pas
│   ├── msProfilePanel.pas
│   ├── msSettingsManager.dfm
│   ├── msSettingsManager.pas
│   ├── msSmash.pas
│   ├── msSmashForm.dfm
│   ├── msSmashForm.pas
│   ├── msSplashForm.dfm
│   ├── msSplashForm.pas
│   ├── msTagHelper.dfm
│   ├── msTagHelper.pas
│   ├── msTagManager.dfm
│   ├── msTagManager.pas
│   ├── msThreads.pas
│   ├── settings/
│   │   ├── Fallout3/
│   │   │   └── Smash.All.json
│   │   ├── Fallout4/
│   │   │   └── Smash.All.json
│   │   ├── FalloutNV/
│   │   │   └── Smash.All.json
│   │   ├── Oblivion/
│   │   │   ├── Bash.Actors.ACBS.json
│   │   │   ├── Bash.Actors.AIData.json
│   │   │   ├── Bash.Actors.AIPackages.json
│   │   │   ├── Bash.Actors.Animations.json
│   │   │   ├── Bash.Actors.CombatStyle.json
│   │   │   ├── Bash.Actors.DeathItem.json
│   │   │   ├── Bash.Actors.Skeleton.json
│   │   │   ├── Bash.Actors.Spells.json
│   │   │   ├── Bash.Actors.Stats.json
│   │   │   ├── Bash.Body-F.json
│   │   │   ├── Bash.Body-M.json
│   │   │   ├── Bash.Body-Size-F.json
│   │   │   ├── Bash.Body-Size-M.json
│   │   │   ├── Bash.C.Climate.json
│   │   │   ├── Bash.C.Light.json
│   │   │   ├── Bash.C.Music.json
│   │   │   ├── Bash.C.Name.json
│   │   │   ├── Bash.C.Owner.json
│   │   │   ├── Bash.C.RecordFlags.json
│   │   │   ├── Bash.C.Water.json
│   │   │   ├── Bash.Creatures.Blood.json
│   │   │   ├── Bash.Eyes.json
│   │   │   ├── Bash.Factions.json
│   │   │   ├── Bash.Graphics.json
│   │   │   ├── Bash.Hair.json
│   │   │   ├── Bash.Invent.json
│   │   │   ├── Bash.Lev.json
│   │   │   ├── Bash.NPC.Class.json
│   │   │   ├── Bash.NPC.Race.json
│   │   │   ├── Bash.Names.json
│   │   │   ├── Bash.Npc.EyesOnly.json
│   │   │   ├── Bash.Npc.HairOnly.json
│   │   │   ├── Bash.NpcFaces.json
│   │   │   ├── Bash.NpcFacesForceFullImport.json
│   │   │   ├── Bash.R.AddSpells.json
│   │   │   ├── Bash.R.Attributes-F.json
│   │   │   ├── Bash.R.Attributes-M.json
│   │   │   ├── Bash.R.ChangeSpells.json
│   │   │   ├── Bash.R.Description.json
│   │   │   ├── Bash.Relations.json
│   │   │   ├── Bash.Scripts.json
│   │   │   ├── Bash.Sound.json
│   │   │   ├── Bash.SpellStats.json
│   │   │   ├── Bash.Stats.json
│   │   │   ├── Bash.Voice-F.json
│   │   │   ├── Bash.Voice-M.json
│   │   │   └── Smash.All.json
│   │   └── Skyrim/
│   │       ├── Bash.Actors.ACBS.json
│   │       ├── Bash.Actors.AIData.json
│   │       ├── Bash.Actors.AIPackages.json
│   │       ├── Bash.Actors.AIPackagesMerge.json
│   │       ├── Bash.Actors.CombatStyle.json
│   │       ├── Bash.Actors.DeathItem.json
│   │       ├── Bash.Actors.Spells.json
│   │       ├── Bash.Actors.SpellsMerge.json
│   │       ├── Bash.Actors.Stats.json
│   │       ├── Bash.All.json
│   │       ├── Bash.Body-F.json
│   │       ├── Bash.Body-M.json
│   │       ├── Bash.Body-Size-F.json
│   │       ├── Bash.Body-Size-M.json
│   │       ├── Bash.C.Acoustic.json
│   │       ├── Bash.C.Climate.json
│   │       ├── Bash.C.Encounter.json
│   │       ├── Bash.C.ImageSpace.json
│   │       ├── Bash.C.Light.json
│   │       ├── Bash.C.Location.json
│   │       ├── Bash.C.Music.json
│   │       ├── Bash.C.Name.json
│   │       ├── Bash.C.Owner.json
│   │       ├── Bash.C.RecordFlags.json
│   │       ├── Bash.C.Regions.json
│   │       ├── Bash.C.Water.json
│   │       ├── Bash.Delev.json
│   │       ├── Bash.Eyes.json
│   │       ├── Bash.Factions.json
│   │       ├── Bash.Graphics.json
│   │       ├── Bash.Hairs.json
│   │       ├── Bash.Invent.json
│   │       ├── Bash.Lev.json
│   │       ├── Bash.NPC.Class.json
│   │       ├── Bash.NPC.Race.json
│   │       ├── Bash.Names.json
│   │       ├── Bash.NpcFaces.json
│   │       ├── Bash.NpcFacesForceFullImport.json
│   │       ├── Bash.R.AddSpells.json
│   │       ├── Bash.R.ChangeSpells.json
│   │       ├── Bash.R.Description.json
│   │       ├── Bash.R.Head.json
│   │       ├── Bash.R.Skills.json
│   │       ├── Bash.Relations.json
│   │       ├── Bash.Relev.json
│   │       ├── Bash.Scripts.json
│   │       ├── Bash.Sound.json
│   │       ├── Bash.SpellStats.json
│   │       ├── Bash.Stats.json
│   │       ├── Bash.Voice-F.json
│   │       ├── Bash.Voice-M.json
│   │       ├── Skip.json
│   │       ├── Smash.All.json
│   │       ├── Smash.ForceAll.json
│   │       └── Smash.OverrideAll.json
│   ├── smash.rc
│   └── smash.res
└── lib/
    ├── Imaging/
    │   ├── Imaging.pas
    │   ├── ImagingBitmap.pas
    │   ├── ImagingCanvases.pas
    │   ├── ImagingClasses.pas
    │   ├── ImagingColors.pas
    │   ├── ImagingComponents.pas
    │   ├── ImagingDds.pas
    │   ├── ImagingFormats.pas
    │   ├── ImagingIO.pas
    │   ├── ImagingNetworkGraphics.pas
    │   ├── ImagingOptions.inc
    │   ├── ImagingTarga.pas
    │   ├── ImagingTypes.pas
    │   ├── ImagingUtility.pas
    │   └── ZLib/
    │       ├── dzlib.pas
    │       ├── imadler.pas
    │       ├── iminfblock.pas
    │       ├── iminfcodes.pas
    │       ├── iminffast.pas
    │       ├── iminftrees.pas
    │       ├── iminfutil.pas
    │       ├── impaszlib.pas
    │       ├── imtrees.pas
    │       ├── imzconf.inc
    │       ├── imzdeflate.pas
    │       ├── imzinflate.pas
    │       ├── imzutil.pas
    │       └── readme.txt
    ├── abbrevia/
    │   ├── MPL-1_1.txt
    │   ├── Readme.html
    │   ├── WavPack License.txt
    │   ├── examples/
    │   │   └── Delphi/
    │   │       ├── Abbrexam.dpr
    │   │       ├── BaseDlgu.pas
    │   │       ├── Basedlgu.dfm
    │   │       ├── CabExt.dpr
    │   │       ├── CabExt1.dfm
    │   │       ├── CabExt1.pas
    │   │       ├── CabFind.dpr
    │   │       ├── CabFind1.dfm
    │   │       ├── CabFind1.pas
    │   │       ├── CabView.dpr
    │   │       ├── CabView1.dfm
    │   │       ├── CabView1.pas
    │   │       ├── ComCtrlsDemo.dpr
    │   │       ├── ComCtrlsMain.dfm
    │   │       ├── ComCtrlsMain.pas
    │   │       ├── CompPad.dpr
    │   │       ├── Contents.dpr
    │   │       ├── Demo.cab
    │   │       ├── ExCBrows.dpr
    │   │       ├── ExCBrowu.dfm
    │   │       ├── ExCBrowu.pas
    │   │       ├── ExCf.dpr
    │   │       ├── ExCf.res
    │   │       ├── ExFilter.dpr
    │   │       ├── ExFiltru.dfm
    │   │       ├── ExFiltru.pas
    │   │       ├── ExZipper.dpr
    │   │       ├── ExZippru.dfm
    │   │       ├── ExZippru.pas
    │   │       ├── FCITest1.dfm
    │   │       ├── FCITest1.pas
    │   │       ├── Finder.dpr
    │   │       ├── MakeCab.dpr
    │   │       ├── MakeCab1.dfm
    │   │       ├── MakeCab1.pas
    │   │       ├── SelfStbv.dpr
    │   │       ├── SelfStub.dpr
    │   │       ├── SlfStbv1.dfm
    │   │       ├── SlfStbv1.pas
    │   │       ├── Streams.dpr
    │   │       ├── Streams1.dfm
    │   │       ├── Streams1.pas
    │   │       ├── StrmBmp.dpr
    │   │       ├── StrmBmpU.dfm
    │   │       ├── StrmBmpU.pas
    │   │       ├── StrmPad.dpr
    │   │       ├── TpZip.RC
    │   │       ├── TpZip.dpr
    │   │       ├── TpZip.r32
    │   │       ├── TpZip31.HLP
    │   │       ├── UContent.dfm
    │   │       ├── UContent.pas
    │   │       ├── UMain.dfm
    │   │       ├── UMain.pas
    │   │       ├── Uexample.dfm
    │   │       ├── Uexample.pas
    │   │       ├── Unzip.dpr
    │   │       ├── Unzip.dproj
    │   │       ├── Unzip.dproj.2007
    │   │       ├── UsingApi.dpr
    │   │       ├── Ustrpad.dfm
    │   │       ├── Ustrpad.pas
    │   │       ├── Uunzip.dfm
    │   │       ├── Uunzip.pas
    │   │       ├── Uzip.dfm
    │   │       ├── Uzip.pas
    │   │       ├── ZipReg.dpr
    │   │       ├── ZipReg.dproj
    │   │       ├── ZipReg.dproj.2007
    │   │       ├── ZipReg1.dfm
    │   │       ├── ZipReg1.pas
    │   │       ├── ZipView.dpr
    │   │       ├── ZipView1.dfm
    │   │       ├── ZipView1.pas
    │   │       ├── Zipper.dpr
    │   │       ├── Zipper.dproj
    │   │       ├── Zipper.dproj.2007
    │   │       ├── dgAbout.dfm
    │   │       ├── dgAbout.pas
    │   │       ├── makesfx.dpr
    │   │       ├── spntst0.dfm
    │   │       ├── spntst0.pas
    │   │       ├── uCfGenDg.dfm
    │   │       ├── uCfGenDg.pas
    │   │       ├── uCfMain.dfm
    │   │       ├── uCfMain.pas
    │   │       ├── uCfNewDg.dfm
    │   │       ├── uCfNewDg.pas
    │   │       ├── ubasedlg.dfm
    │   │       ├── ubasedlg.pas
    │   │       ├── ucomppad.dfm
    │   │       ├── ucomppad.pas
    │   │       ├── udemodlg.dfm
    │   │       ├── udemodlg.pas
    │   │       ├── ufinder.dfm
    │   │       ├── ufinder.pas
    │   │       ├── umakesfx.dfm
    │   │       ├── umakesfx.pas
    │   │       ├── usplash.dfm
    │   │       └── usplash.pas
    │   ├── localization/
    │   │   ├── AbResString.pas.afr
    │   │   ├── AbResString.pas.de
    │   │   ├── AbResString.pas.fr
    │   │   ├── AbResString.pas.nl
    │   │   ├── AbResString.pas.ru
    │   │   └── AbResString.pas.tr
    │   ├── packages/
    │   │   ├── Delphi XE/
    │   │   │   ├── Abbrevia.dpk
    │   │   │   ├── Abbrevia.dproj
    │   │   │   ├── Abbrevia.res
    │   │   │   ├── AbbreviaVCL.dpk
    │   │   │   ├── AbbreviaVCL.dproj
    │   │   │   ├── AbbreviaVCL.res
    │   │   │   ├── AbbreviaVCLDesign.dpk
    │   │   │   ├── AbbreviaVCLDesign.dproj
    │   │   │   └── AbbreviaVCLDesign.res
    │   │   └── Delphi XE.groupproj
    │   └── source/
    │       ├── AbArcTyp.pas
    │       ├── AbBase.pas
    │       ├── AbBitBkt.pas
    │       ├── AbBrowse.pas
    │       ├── AbBseCLX.pas
    │       ├── AbBseVCL.pas
    │       ├── AbBzip2.pas
    │       ├── AbBzip2Typ.pas
    │       ├── AbCBrows.pas
    │       ├── AbCView.pas
    │       ├── AbCabExt.pas
    │       ├── AbCabKit.pas
    │       ├── AbCabMak.pas
    │       ├── AbCabTyp.pas
    │       ├── AbCharset.pas
    │       ├── AbComCtrls.pas
    │       ├── AbComCtrls.res
    │       ├── AbCompnd.pas
    │       ├── AbConst.pas
    │       ├── AbCrtl.pas
    │       ├── AbDefine.inc
    │       ├── AbDfBase.pas
    │       ├── AbDfCryS.pas
    │       ├── AbDfDec.pas
    │       ├── AbDfEnc.pas
    │       ├── AbDfHufD.pas
    │       ├── AbDfInW.pas
    │       ├── AbDfOutW.pas
    │       ├── AbDfPkMg.pas
    │       ├── AbDfStrm.pas
    │       ├── AbDfXlat.pas
    │       ├── AbDlgDir.dfm
    │       ├── AbDlgDir.pas
    │       ├── AbDlgPwd.dfm
    │       ├── AbDlgPwd.pas
    │       ├── AbExcept.pas
    │       ├── AbFciFdi.pas
    │       ├── AbGzTyp.pas
    │       ├── AbHexVw.pas
    │       ├── AbLZMA.pas
    │       ├── AbLZMAStream.pas
    │       ├── AbMeter.pas
    │       ├── AbPPMd.pas
    │       ├── AbPeCol.dfm
    │       ├── AbPeCol.pas
    │       ├── AbPeDir.pas
    │       ├── AbPeFn.pas
    │       ├── AbPePass.pas
    │       ├── AbPeVer.dfm
    │       ├── AbPeVer.pas
    │       ├── AbQCView.pas
    │       ├── AbQCmpnd.pas
    │       ├── AbQDgDir.pas
    │       ├── AbQDgDir.xfm
    │       ├── AbQDgPwd.pas
    │       ├── AbQDgPwd.xfm
    │       ├── AbQHexVw.pas
    │       ├── AbQMeter.pas
    │       ├── AbQPeCol.pas
    │       ├── AbQPeCol.xfm
    │       ├── AbQPeDir.pas
    │       ├── AbQPeFn.pas
    │       ├── AbQPePas.pas
    │       ├── AbQPeVer.pas
    │       ├── AbQPeVer.xfm
    │       ├── AbQView.pas
    │       ├── AbQZView.pas
    │       ├── AbQZpOut.pas
    │       ├── AbReg.pas
    │       ├── AbReg.res
    │       ├── AbRegClx.pas
    │       ├── AbRegLinux.pas
    │       ├── AbRegVcl.pas
    │       ├── AbResString.pas
    │       ├── AbSWStm.pas
    │       ├── AbSelfEx.pas
    │       ├── AbSpanSt.pas
    │       ├── AbTarTyp.pas
    │       ├── AbUnzOutStm.pas
    │       ├── AbUnzPrc.pas
    │       ├── AbUnzper.pas
    │       ├── AbUtils.pas
    │       ├── AbVMStrm.pas
    │       ├── AbView.pas
    │       ├── AbWavPack.pas
    │       ├── AbZBrows.pas
    │       ├── AbZLTyp.pas
    │       ├── AbZView.pas
    │       ├── AbZipExt.pas
    │       ├── AbZipKit.pas
    │       ├── AbZipOut.pas
    │       ├── AbZipOut.res
    │       ├── AbZipPrc.pas
    │       ├── AbZipTyp.pas
    │       ├── AbZipper.pas
    │       ├── COM/
    │       │   ├── Abbrevia.dpr
    │       │   ├── Abbrevia.dproj
    │       │   ├── Abbrevia.res
    │       │   ├── Abbrevia.ridl
    │       │   ├── Abbrevia.tlb
    │       │   ├── Abbrevia_TLB.pas
    │       │   ├── Readme.txt
    │       │   ├── _GZipItem.pas
    │       │   ├── _TarItem.pas
    │       │   ├── _ZipItem.pas
    │       │   └── _ZipKit.pas
    │       ├── Win32/
    │       │   ├── CarrylessRangeCoder.obj
    │       │   ├── LzFind.obj
    │       │   ├── LzFindMt.obj
    │       │   ├── LzmaDec.obj
    │       │   ├── LzmaEnc.obj
    │       │   ├── PPMdContext.obj
    │       │   ├── PPMdSubAllocatorVariantI.obj
    │       │   ├── PPMdVariantI.obj
    │       │   ├── Threads.obj
    │       │   ├── blocksort.obj
    │       │   ├── bzlib.obj
    │       │   ├── compress.obj
    │       │   ├── decompress.obj
    │       │   ├── huffman.obj
    │       │   ├── wv_bits.obj
    │       │   ├── wv_extra1.obj
    │       │   ├── wv_extra2.obj
    │       │   ├── wv_float.obj
    │       │   ├── wv_metadata.obj
    │       │   ├── wv_pack.obj
    │       │   ├── wv_tags.obj
    │       │   ├── wv_unpack.obj
    │       │   ├── wv_unpack3.obj
    │       │   ├── wv_words.obj
    │       │   └── wv_wputils.obj
    │       └── Win64/
    │           ├── CarrylessRangeCoder.obj
    │           ├── LzFind.obj
    │           ├── LzFindMt.obj
    │           ├── LzmaDec.obj
    │           ├── LzmaEnc.obj
    │           ├── PPMdContext.obj
    │           ├── PPMdSubAllocatorVariantI.obj
    │           ├── PPMdVariantI.obj
    │           ├── Threads.obj
    │           ├── blocksort.obj
    │           ├── bzlib.obj
    │           ├── compress.obj
    │           ├── decompress.obj
    │           ├── huffman.obj
    │           ├── wv_bits.obj
    │           ├── wv_extra1.obj
    │           ├── wv_extra2.obj
    │           ├── wv_float.obj
    │           ├── wv_metadata.obj
    │           ├── wv_pack.obj
    │           ├── wv_tags.obj
    │           ├── wv_unpack.obj
    │           ├── wv_unpack3.obj
    │           ├── wv_words.obj
    │           └── wv_wputils.obj
    ├── mte/
    │   ├── CRC32.pas
    │   ├── RttiIni.pas
    │   ├── RttiJson.pas
    │   ├── RttiTranslation.pas
    │   ├── W7Taskbar.pas
    │   ├── mteBase.pas
    │   ├── mteChangeLogForm.dfm
    │   ├── mteChangeLogForm.pas
    │   ├── mteHelpers.pas
    │   ├── mteLogger.pas
    │   ├── mteLogging.pas
    │   ├── mtePluginSelectionForm.dfm
    │   ├── mtePluginSelectionForm.pas
    │   ├── mteProgressForm.dfm
    │   ├── mteProgressForm.pas
    │   ├── mteTaskHandler.pas
    │   └── mteTracker.pas
    ├── superobject/
    │   └── superobject.pas
    ├── xedit/
    │   ├── lz4/
    │   │   ├── lz4.pas
    │   │   ├── lz4Common.pas
    │   │   ├── lz4HC.pas
    │   │   ├── lz4frame.pas
    │   │   ├── lz4frame_static.pas
    │   │   ├── lz4io.pas
    │   │   └── xxHash.pas
    │   ├── wbBSA.pas
    │   ├── wbDefines.inc
    │   ├── wbDefinitionsFNV.pas
    │   ├── wbDefinitionsFO3.pas
    │   ├── wbDefinitionsFO4.pas
    │   ├── wbDefinitionsTES3.pas
    │   ├── wbDefinitionsTES4.pas
    │   ├── wbDefinitionsTES5.pas
    │   ├── wbHelpers.pas
    │   ├── wbImplementation.pas
    │   ├── wbInit.pas
    │   ├── wbInterface.pas
    │   ├── wbLocalization.pas
    │   ├── wbSort.pas
    │   ├── wbStreams.pas
    │   └── zlib/
    │       ├── ZLibEx.inc
    │       ├── ZLibExApi.pas
    │       ├── win32/
    │       │   ├── adler32.obj
    │       │   ├── compress.obj
    │       │   ├── crc32.obj
    │       │   ├── deflate.obj
    │       │   ├── infback.obj
    │       │   ├── inffast.obj
    │       │   ├── inflate.obj
    │       │   ├── inftrees.obj
    │       │   └── trees.obj
    │       ├── win64/
    │       │   ├── adler32.obj
    │       │   ├── compress.obj
    │       │   ├── crc32.obj
    │       │   ├── deflate.obj
    │       │   ├── infback.obj
    │       │   ├── inffast.obj
    │       │   ├── inflate.obj
    │       │   ├── inftrees.obj
    │       │   └── trees.obj
    │       └── zlibex.pas
    └── zeosdbo/
        ├── doc/
        │   └── html/
        │       ├── bugreporting.html
        │       ├── buildingtests.html
        │       ├── changes.html
        │       ├── ede.css
        │       ├── installation.html
        │       ├── knownbugs.html
        │       ├── license.html
        │       ├── overview.html
        │       ├── parameters.html
        │       └── readme.html
        ├── packages/
        │   └── DelphiXE/
        │       ├── ZComponent.dpk
        │       ├── ZComponent.dproj
        │       ├── ZComponent.res
        │       ├── ZComponentDesign.dpk
        │       ├── ZComponentDesign.dproj
        │       ├── ZComponentDesign.res
        │       ├── ZCore.dpk
        │       ├── ZCore.dproj
        │       ├── ZCore.res
        │       ├── ZDbc.dpk
        │       ├── ZDbc.dproj
        │       ├── ZDbc.res
        │       ├── ZPackages.inc
        │       ├── ZParseSql.dpk
        │       ├── ZParseSql.dproj
        │       ├── ZParseSql.res
        │       ├── ZPlain.dpk
        │       ├── ZPlain.dproj
        │       ├── ZPlain.res
        │       ├── ZeosDbo.groupproj
        │       └── events good.txt
        └── src/
            ├── Zeos.inc
            ├── ZeosLazarus.inc
            ├── component/
            │   ├── ZAbstractConnection.pas
            │   ├── ZAbstractDataset.pas
            │   ├── ZAbstractRODataset.pas
            │   ├── ZAbstractTable.pas
            │   ├── ZComponent.dcr
            │   ├── ZComponent.inc
            │   ├── ZComponentReg.lrs
            │   ├── ZComponentReg.pas
            │   ├── ZConnection.pas
            │   ├── ZConnectionGroup.pas
            │   ├── ZDataset.pas
            │   ├── ZDatasetUtils.pas
            │   ├── ZGroupedConnection.pas
            │   ├── ZIBEventAlerter.pas
            │   ├── ZPgEventAlerter.pas
            │   ├── ZPropertyEditor.pas
            │   ├── ZQuerySQLEditor.pas
            │   ├── ZROSqlEditor.pas
            │   ├── ZSequence.pas
            │   ├── ZSqlMetadata.pas
            │   ├── ZSqlMonitor.pas
            │   ├── ZSqlProcessor.pas
            │   ├── ZSqlStrings.pas
            │   ├── ZSqlTestForm.pas
            │   ├── ZSqlUpdate.pas
            │   ├── ZStoredProcedure.pas
            │   ├── ZStreamBlob.pas
            │   ├── ZUpdateSqlEditor.dfm
            │   ├── ZUpdateSqlEditor.lfm
            │   ├── ZUpdateSqlEditor.lrs
            │   └── ZUpdateSqlEditor.pas
            ├── core/
            │   ├── ZClasses.pas
            │   ├── ZCollections.pas
            │   ├── ZCompatibility.pas
            │   ├── ZCore.inc
            │   ├── ZEncoding.pas
            │   ├── ZExprParser.pas
            │   ├── ZExprToken.pas
            │   ├── ZExpression.pas
            │   ├── ZFunctions.pas
            │   ├── ZFunctionsConvert.pas
            │   ├── ZFunctionsDateTime.pas
            │   ├── ZFunctionsMath.pas
            │   ├── ZFunctionsOther.pas
            │   ├── ZFunctionsStrings.pas
            │   ├── ZMatchPattern.pas
            │   ├── ZMessages.pas
            │   ├── ZSysUtils.pas
            │   ├── ZTokenizer.pas
            │   ├── ZURL.pas
            │   ├── ZVariables.pas
            │   └── ZVariant.pas
            ├── dbc/
            │   ├── ZDbc.inc
            │   ├── ZDbcASA.pas
            │   ├── ZDbcASAMetadata.pas
            │   ├── ZDbcASAResultSet.pas
            │   ├── ZDbcASAStatement.pas
            │   ├── ZDbcASAUtils.pas
            │   ├── ZDbcAdo.pas
            │   ├── ZDbcAdoMetadata.pas
            │   ├── ZDbcAdoResultSet.pas
            │   ├── ZDbcAdoStatement.pas
            │   ├── ZDbcAdoUtils.pas
            │   ├── ZDbcCache.pas
            │   ├── ZDbcCachedResultSet.pas
            │   ├── ZDbcConnection.pas
            │   ├── ZDbcDbLib.pas
            │   ├── ZDbcDbLibMetadata.pas
            │   ├── ZDbcDbLibResultSet.pas
            │   ├── ZDbcDbLibStatement.pas
            │   ├── ZDbcDbLibUtils.pas
            │   ├── ZDbcGenericResolver.pas
            │   ├── ZDbcInterbase6.pas
            │   ├── ZDbcInterbase6Metadata.pas
            │   ├── ZDbcInterbase6ResultSet.pas
            │   ├── ZDbcInterbase6Statement.pas
            │   ├── ZDbcInterbase6Utils.pas
            │   ├── ZDbcIntfs.pas
            │   ├── ZDbcLogging.pas
            │   ├── ZDbcMetadata.pas
            │   ├── ZDbcMySql.pas
            │   ├── ZDbcMySqlMetadata.pas
            │   ├── ZDbcMySqlResultSet.pas
            │   ├── ZDbcMySqlStatement.pas
            │   ├── ZDbcMySqlUtils.pas
            │   ├── ZDbcOracle.pas
            │   ├── ZDbcOracleMetadata.pas
            │   ├── ZDbcOracleResultSet.pas
            │   ├── ZDbcOracleStatement.pas
            │   ├── ZDbcOracleUtils.pas
            │   ├── ZDbcPooled.pas
            │   ├── ZDbcPostgreSql.pas
            │   ├── ZDbcPostgreSqlMetadata.pas
            │   ├── ZDbcPostgreSqlResultSet.pas
            │   ├── ZDbcPostgreSqlStatement.pas
            │   ├── ZDbcPostgreSqlUtils.pas
            │   ├── ZDbcResultSet.pas
            │   ├── ZDbcResultSetMetadata.pas
            │   ├── ZDbcSqLite.pas
            │   ├── ZDbcSqLiteMetadata.pas
            │   ├── ZDbcSqLiteResultSet.pas
            │   ├── ZDbcSqLiteStatement.pas
            │   ├── ZDbcSqLiteUtils.pas
            │   ├── ZDbcStatement.pas
            │   └── ZDbcUtils.pas
            ├── parsesql/
            │   ├── ZAdoToken.pas
            │   ├── ZGenericSqlAnalyser.pas
            │   ├── ZGenericSqlToken.pas
            │   ├── ZInterbaseAnalyser.pas
            │   ├── ZInterbaseToken.pas
            │   ├── ZMySqlAnalyser.pas
            │   ├── ZMySqlToken.pas
            │   ├── ZOracleAnalyser.pas
            │   ├── ZOracleToken.pas
            │   ├── ZParseSql.inc
            │   ├── ZPostgreSqlAnalyser.pas
            │   ├── ZPostgreSqlToken.pas
            │   ├── ZScriptParser.pas
            │   ├── ZSelectSchema.pas
            │   ├── ZSqLiteAnalyser.pas
            │   ├── ZSqLiteToken.pas
            │   ├── ZSybaseAnalyser.pas
            │   └── ZSybaseToken.pas
            ├── plain/
            │   ├── ZPlain.inc
            │   ├── ZPlainASAConstants.pas
            │   ├── ZPlainASADriver.pas
            │   ├── ZPlainAdo.pas
            │   ├── ZPlainAdoDriver.pas
            │   ├── ZPlainDbLibConstants.pas
            │   ├── ZPlainDbLibDriver.pas
            │   ├── ZPlainDriver.pas
            │   ├── ZPlainFirebirdDriver.pas
            │   ├── ZPlainFirebirdInterbaseConstants.pas
            │   ├── ZPlainLoader.pas
            │   ├── ZPlainMySqlConstants.pas
            │   ├── ZPlainMySqlDriver.pas
            │   ├── ZPlainOracleConstants.pas
            │   ├── ZPlainOracleDriver.pas
            │   ├── ZPlainPostgreSqlDriver.pas
            │   └── ZPlainSqLiteDriver.pas
            ├── repl.awk
            ├── repl.instructions
            └── repl.txt

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Uncomment these types if you want even more clean repository. But be careful.
# It can make harm to an existing project source. Read explanations below.
#
# Resource files are binaries containing manifest, project icon and version info.
# They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files.
#*.res
#
# Type library file (binary). In old Delphi versions it should be stored.
# Since Delphi 2009 it is produced from .ridl file and can safely be ignored.
#*.tlb
#
# Diagram Portfolio file. Used by the diagram editor up to Delphi 7.
# Uncomment this if you are not using diagrams or use newer Delphi version.
#*.ddp
#
# Visual LiveBindings file. Added in Delphi XE2.
# Uncomment this if you are not using LiveBindings Designer.
#*.vlb
#
# Deployment Manager configuration file for your project. Added in Delphi XE2.
# Uncomment this if it is not mobile development and you do not use remote debug feature.
#*.deployproj
#

# Delphi compiler-generated binaries (safe to delete)
*.exe
*.dll
*.bpl
*.bpi
*.dcp
*.so
*.apk
*.drc
*.map
*.dres
*.rsm
*.tds
*.dcu
*.lib

# Delphi autogenerated files (duplicated info)
*.cfg
*Resource.rc

# Delphi local files (user-specific info)
*.local
*.identcache
*.projdata
*.tvsconfig
*.dsk

# Delphi history and backups
__history/
*.~*

# Castalia statistics file
*.stat

# Repository ignore
*.ini
*.zip
backend/logs/*.txt
loc/
test/
frontend/__history/
frontend/logs/
frontend/patches/
*.txaPackage
frontend/profiles/


================================================
FILE: LICENSE.txt
================================================
                          MOZILLA PUBLIC LICENSE
                                Version 1.1

                              ---------------

1. Definitions.

     1.0.1. "Commercial Use" means distribution or otherwise making the
     Covered Code available to a third party.

     1.1. "Contributor" means each entity that creates or contributes to
     the creation of Modifications.

     1.2. "Contributor Version" means the combination of the Original
     Code, prior Modifications used by a Contributor, and the Modifications
     made by that particular Contributor.

     1.3. "Covered Code" means the Original Code or Modifications or the
     combination of the Original Code and Modifications, in each case
     including portions thereof.

     1.4. "Electronic Distribution Mechanism" means a mechanism generally
     accepted in the software development community for the electronic
     transfer of data.

     1.5. "Executable" means Covered Code in any form other than Source
     Code.

     1.6. "Initial Developer" means the individual or entity identified
     as the Initial Developer in the Source Code notice required by Exhibit
     A.

     1.7. "Larger Work" means a work which combines Covered Code or
     portions thereof with code not governed by the terms of this License.

     1.8. "License" means this document.

     1.8.1. "Licensable" means having the right to grant, to the maximum
     extent possible, whether at the time of the initial grant or
     subsequently acquired, any and all of the rights conveyed herein.

     1.9. "Modifications" means any addition to or deletion from the
     substance or structure of either the Original Code or any previous
     Modifications. When Covered Code is released as a series of files, a
     Modification is:
          A. Any addition to or deletion from the contents of a file
          containing Original Code or previous Modifications.

          B. Any new file that contains any part of the Original Code or
          previous Modifications.

     1.10. "Original Code" means Source Code of computer software code
     which is described in the Source Code notice required by Exhibit A as
     Original Code, and which, at the time of its release under this
     License is not already Covered Code governed by this License.

     1.10.1. "Patent Claims" means any patent claim(s), now owned or
     hereafter acquired, including without limitation,  method, process,
     and apparatus claims, in any patent Licensable by grantor.

     1.11. "Source Code" means the preferred form of the Covered Code for
     making modifications to it, including all modules it contains, plus
     any associated interface definition files, scripts used to control
     compilation and installation of an Executable, or source code
     differential comparisons against either the Original Code or another
     well known, available Covered Code of the Contributor's choice. The
     Source Code can be in a compressed or archival form, provided the
     appropriate decompression or de-archiving software is widely available
     for no charge.

     1.12. "You" (or "Your")  means an individual or a legal entity
     exercising rights under, and complying with all of the terms of, this
     License or a future version of this License issued under Section 6.1.
     For legal entities, "You" includes any entity which controls, is
     controlled by, or is under common control with You. For purposes of
     this definition, "control" means (a) the power, direct or indirect,
     to cause the direction or management of such entity, whether by
     contract or otherwise, or (b) ownership of more than fifty percent
     (50%) of the outstanding shares or beneficial ownership of such
     entity.

2. Source Code License.

     2.1. The Initial Developer Grant.
     The Initial Developer hereby grants You a world-wide, royalty-free,
     non-exclusive license, subject to third party intellectual property
     claims:
          (a)  under intellectual property rights (other than patent or
          trademark) Licensable by Initial Developer to use, reproduce,
          modify, display, perform, sublicense and distribute the Original
          Code (or portions thereof) with or without Modifications, and/or
          as part of a Larger Work; and

          (b) under Patents Claims infringed by the making, using or
          selling of Original Code, to make, have made, use, practice,
          sell, and offer for sale, and/or otherwise dispose of the
          Original Code (or portions thereof).

          (c) the licenses granted in this Section 2.1(a) and (b) are
          effective on the date Initial Developer first distributes
          Original Code under the terms of this License.

          (d) Notwithstanding Section 2.1(b) above, no patent license is
          granted: 1) for code that You delete from the Original Code; 2)
          separate from the Original Code;  or 3) for infringements caused
          by: i) the modification of the Original Code or ii) the
          combination of the Original Code with other software or devices.

     2.2. Contributor Grant.
     Subject to third party intellectual property claims, each Contributor
     hereby grants You a world-wide, royalty-free, non-exclusive license

          (a)  under intellectual property rights (other than patent or
          trademark) Licensable by Contributor, to use, reproduce, modify,
          display, perform, sublicense and distribute the Modifications
          created by such Contributor (or portions thereof) either on an
          unmodified basis, with other Modifications, as Covered Code
          and/or as part of a Larger Work; and

          (b) under Patent Claims infringed by the making, using, or
          selling of  Modifications made by that Contributor either alone
          and/or in combination with its Contributor Version (or portions
          of such combination), to make, use, sell, offer for sale, have
          made, and/or otherwise dispose of: 1) Modifications made by that
          Contributor (or portions thereof); and 2) the combination of
          Modifications made by that Contributor with its Contributor
          Version (or portions of such combination).

          (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
          effective on the date Contributor first makes Commercial Use of
          the Covered Code.

          (d)    Notwithstanding Section 2.2(b) above, no patent license is
          granted: 1) for any code that Contributor has deleted from the
          Contributor Version; 2)  separate from the Contributor Version;
          3)  for infringements caused by: i) third party modifications of
          Contributor Version or ii)  the combination of Modifications made
          by that Contributor with other software  (except as part of the
          Contributor Version) or other devices; or 4) under Patent Claims
          infringed by Covered Code in the absence of Modifications made by
          that Contributor.

3. Distribution Obligations.

     3.1. Application of License.
     The Modifications which You create or to which You contribute are
     governed by the terms of this License, including without limitation
     Section 2.2. The Source Code version of Covered Code may be
     distributed only under the terms of this License or a future version
     of this License released under Section 6.1, and You must include a
     copy of this License with every copy of the Source Code You
     distribute. You may not offer or impose any terms on any Source Code
     version that alters or restricts the applicable version of this
     License or the recipients' rights hereunder. However, You may include
     an additional document offering the additional rights described in
     Section 3.5.

     3.2. Availability of Source Code.
     Any Modification which You create or to which You contribute must be
     made available in Source Code form under the terms of this License
     either on the same media as an Executable version or via an accepted
     Electronic Distribution Mechanism to anyone to whom you made an
     Executable version available; and if made available via Electronic
     Distribution Mechanism, must remain available for at least twelve (12)
     months after the date it initially became available, or at least six
     (6) months after a subsequent version of that particular Modification
     has been made available to such recipients. You are responsible for
     ensuring that the Source Code version remains available even if the
     Electronic Distribution Mechanism is maintained by a third party.

     3.3. Description of Modifications.
     You must cause all Covered Code to which You contribute to contain a
     file documenting the changes You made to create that Covered Code and
     the date of any change. You must include a prominent statement that
     the Modification is derived, directly or indirectly, from Original
     Code provided by the Initial Developer and including the name of the
     Initial Developer in (a) the Source Code, and (b) in any notice in an
     Executable version or related documentation in which You describe the
     origin or ownership of the Covered Code.

     3.4. Intellectual Property Matters
          (a) Third Party Claims.
          If Contributor has knowledge that a license under a third party's
          intellectual property rights is required to exercise the rights
          granted by such Contributor under Sections 2.1 or 2.2,
          Contributor must include a text file with the Source Code
          distribution titled "LEGAL" which describes the claim and the
          party making the claim in sufficient detail that a recipient will
          know whom to contact. If Contributor obtains such knowledge after
          the Modification is made available as described in Section 3.2,
          Contributor shall promptly modify the LEGAL file in all copies
          Contributor makes available thereafter and shall take other steps
          (such as notifying appropriate mailing lists or newsgroups)
          reasonably calculated to inform those who received the Covered
          Code that new knowledge has been obtained.

          (b) Contributor APIs.
          If Contributor's Modifications include an application programming
          interface and Contributor has knowledge of patent licenses which
          are reasonably necessary to implement that API, Contributor must
          also include this information in the LEGAL file.

               (c)    Representations.
          Contributor represents that, except as disclosed pursuant to
          Section 3.4(a) above, Contributor believes that Contributor's
          Modifications are Contributor's original creation(s) and/or
          Contributor has sufficient rights to grant the rights conveyed by
          this License.

     3.5. Required Notices.
     You must duplicate the notice in Exhibit A in each file of the Source
     Code.  If it is not possible to put such notice in a particular Source
     Code file due to its structure, then You must include such notice in a
     location (such as a relevant directory) where a user would be likely
     to look for such a notice.  If You created one or more Modification(s)
     You may add your name as a Contributor to the notice described in
     Exhibit A.  You must also duplicate this License in any documentation
     for the Source Code where You describe recipients' rights or ownership
     rights relating to Covered Code.  You may choose to offer, and to
     charge a fee for, warranty, support, indemnity or liability
     obligations to one or more recipients of Covered Code. However, You
     may do so only on Your own behalf, and not on behalf of the Initial
     Developer or any Contributor. You must make it absolutely clear than
     any such warranty, support, indemnity or liability obligation is
     offered by You alone, and You hereby agree to indemnify the Initial
     Developer and every Contributor for any liability incurred by the
     Initial Developer or such Contributor as a result of warranty,
     support, indemnity or liability terms You offer.

     3.6. Distribution of Executable Versions.
     You may distribute Covered Code in Executable form only if the
     requirements of Section 3.1-3.5 have been met for that Covered Code,
     and if You include a notice stating that the Source Code version of
     the Covered Code is available under the terms of this License,
     including a description of how and where You have fulfilled the
     obligations of Section 3.2. The notice must be conspicuously included
     in any notice in an Executable version, related documentation or
     collateral in which You describe recipients' rights relating to the
     Covered Code. You may distribute the Executable version of Covered
     Code or ownership rights under a license of Your choice, which may
     contain terms different from this License, provided that You are in
     compliance with the terms of this License and that the license for the
     Executable version does not attempt to limit or alter the recipient's
     rights in the Source Code version from the rights set forth in this
     License. If You distribute the Executable version under a different
     license You must make it absolutely clear that any terms which differ
     from this License are offered by You alone, not by the Initial
     Developer or any Contributor. You hereby agree to indemnify the
     Initial Developer and every Contributor for any liability incurred by
     the Initial Developer or such Contributor as a result of any such
     terms You offer.

     3.7. Larger Works.
     You may create a Larger Work by combining Covered Code with other code
     not governed by the terms of this License and distribute the Larger
     Work as a single product. In such a case, You must make sure the
     requirements of this License are fulfilled for the Covered Code.

4. Inability to Comply Due to Statute or Regulation.

     If it is impossible for You to comply with any of the terms of this
     License with respect to some or all of the Covered Code due to
     statute, judicial order, or regulation then You must: (a) comply with
     the terms of this License to the maximum extent possible; and (b)
     describe the limitations and the code they affect. Such description
     must be included in the LEGAL file described in Section 3.4 and must
     be included with all distributions of the Source Code. Except to the
     extent prohibited by statute or regulation, such description must be
     sufficiently detailed for a recipient of ordinary skill to be able to
     understand it.

5. Application of this License.

     This License applies to code to which the Initial Developer has
     attached the notice in Exhibit A and to related Covered Code.

6. Versions of the License.

     6.1. New Versions.
     Netscape Communications Corporation ("Netscape") may publish revised
     and/or new versions of the License from time to time. Each version
     will be given a distinguishing version number.

     6.2. Effect of New Versions.
     Once Covered Code has been published under a particular version of the
     License, You may always continue to use it under the terms of that
     version. You may also choose to use such Covered Code under the terms
     of any subsequent version of the License published by Netscape. No one
     other than Netscape has the right to modify the terms applicable to
     Covered Code created under this License.

     6.3. Derivative Works.
     If You create or use a modified version of this License (which you may
     only do in order to apply it to code which is not already Covered Code
     governed by this License), You must (a) rename Your license so that
     the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
     "MPL", "NPL" or any confusingly similar phrase do not appear in your
     license (except to note that your license differs from this License)
     and (b) otherwise make it clear that Your version of the license
     contains terms which differ from the Mozilla Public License and
     Netscape Public License. (Filling in the name of the Initial
     Developer, Original Code or Contributor in the notice described in
     Exhibit A shall not of themselves be deemed to be modifications of
     this License.)

7. DISCLAIMER OF WARRANTY.

     COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
     WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
     WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
     DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
     THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
     IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
     YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
     COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
     OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
     ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.

8. TERMINATION.

     8.1.  This License and the rights granted hereunder will terminate
     automatically if You fail to comply with terms herein and fail to cure
     such breach within 30 days of becoming aware of the breach. All
     sublicenses to the Covered Code which are properly granted shall
     survive any termination of this License. Provisions which, by their
     nature, must remain in effect beyond the termination of this License
     shall survive.

     8.2.  If You initiate litigation by asserting a patent infringement
     claim (excluding declatory judgment actions) against Initial Developer
     or a Contributor (the Initial Developer or Contributor against whom
     You file such action is referred to as "Participant")  alleging that:

     (a)  such Participant's Contributor Version directly or indirectly
     infringes any patent, then any and all rights granted by such
     Participant to You under Sections 2.1 and/or 2.2 of this License
     shall, upon 60 days notice from Participant terminate prospectively,
     unless if within 60 days after receipt of notice You either: (i)
     agree in writing to pay Participant a mutually agreeable reasonable
     royalty for Your past and future use of Modifications made by such
     Participant, or (ii) withdraw Your litigation claim with respect to
     the Contributor Version against such Participant.  If within 60 days
     of notice, a reasonable royalty and payment arrangement are not
     mutually agreed upon in writing by the parties or the litigation claim
     is not withdrawn, the rights granted by Participant to You under
     Sections 2.1 and/or 2.2 automatically terminate at the expiration of
     the 60 day notice period specified above.

     (b)  any software, hardware, or device, other than such Participant's
     Contributor Version, directly or indirectly infringes any patent, then
     any rights granted to You by such Participant under Sections 2.1(b)
     and 2.2(b) are revoked effective as of the date You first made, used,
     sold, distributed, or had made, Modifications made by that
     Participant.

     8.3.  If You assert a patent infringement claim against Participant
     alleging that such Participant's Contributor Version directly or
     indirectly infringes any patent where such claim is resolved (such as
     by license or settlement) prior to the initiation of patent
     infringement litigation, then the reasonable value of the licenses
     granted by such Participant under Sections 2.1 or 2.2 shall be taken
     into account in determining the amount or value of any payment or
     license.

     8.4.  In the event of termination under Sections 8.1 or 8.2 above,
     all end user license agreements (excluding distributors and resellers)
     which have been validly granted by You or any distributor hereunder
     prior to termination shall survive termination.

9. LIMITATION OF LIABILITY.

     UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
     (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
     DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
     OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
     ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
     CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
     WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
     COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
     INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
     LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
     RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
     PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
     EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
     THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.

10. U.S. GOVERNMENT END USERS.

     The Covered Code is a "commercial item," as that term is defined in
     48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
     software" and "commercial computer software documentation," as such
     terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
     C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
     all U.S. Government End Users acquire Covered Code with only those
     rights set forth herein.

11. MISCELLANEOUS.

     This License represents the complete agreement concerning subject
     matter hereof. If any provision of this License is held to be
     unenforceable, such provision shall be reformed only to the extent
     necessary to make it enforceable. This License shall be governed by
     California law provisions (except to the extent applicable law, if
     any, provides otherwise), excluding its conflict-of-law provisions.
     With respect to disputes in which at least one party is a citizen of,
     or an entity chartered or registered to do business in the United
     States of America, any litigation relating to this License shall be
     subject to the jurisdiction of the Federal Courts of the Northern
     District of California, with venue lying in Santa Clara County,
     California, with the losing party responsible for costs, including
     without limitation, court costs and reasonable attorneys' fees and
     expenses. The application of the United Nations Convention on
     Contracts for the International Sale of Goods is expressly excluded.
     Any law or regulation which provides that the language of a contract
     shall be construed against the drafter shall not apply to this
     License.

12. RESPONSIBILITY FOR CLAIMS.

     As between Initial Developer and the Contributors, each party is
     responsible for claims and damages arising, directly or indirectly,
     out of its utilization of rights under this License and You agree to
     work with Initial Developer and Contributors to distribute such
     responsibility on an equitable basis. Nothing herein is intended or
     shall be deemed to constitute any admission of liability.

13. MULTIPLE-LICENSED CODE.

     Initial Developer may designate portions of the Covered Code as
     "Multiple-Licensed".  "Multiple-Licensed" means that the Initial
     Developer permits you to utilize portions of the Covered Code under
     Your choice of the NPL or the alternative licenses, if any, specified
     by the Initial Developer in the file described in Exhibit A.

EXHIBIT A -Mozilla Public License.

     ``The contents of this file are subject to the Mozilla Public License
     Version 1.1 (the "License"); you may not use this file except in
     compliance with the License. You may obtain a copy of the License at
     http://www.mozilla.org/MPL/

     Software distributed under the License is distributed on an "AS IS"
     basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
     License for the specific language governing rights and limitations
     under the License.

     The Original Code is ______________________________________.

     The Initial Developer of the Original Code is ________________________.
     Portions created by ______________________ are Copyright (C) ______
     _______________________. All Rights Reserved.

     Contributor(s): ______________________________________.

     Alternatively, the contents of this file may be used under the terms
     of the _____ license (the  "[___] License"), in which case the
     provisions of [______] License are applicable instead of those
     above.  If you wish to allow use of your version of this file only
     under the terms of the [____] License and not to allow others to use
     your version of this file under the MPL, indicate your decision by
     deleting  the provisions above and replace  them with the notice and
     other provisions required by the [___] License.  If you do not delete
     the provisions above, a recipient may use your version of this file
     under either the MPL or the [___] License."

     [NOTE: The text of this Exhibit A may differ slightly from the text of
     the notices in the Source Code files of the Original Code. You should
     use the text of this Exhibit A rather than the text found in the
     Original Code Source Code for Your Modifications.]

================================================
FILE: README.md
================================================
# smash
A tool for performing automatic conflict resolution between multiple Bethesda Plugin Files for TES and Fallout games.

## explanation
Characters, items, quests, music tracks, leveled lists, weathers, magical effects, etc. are all represented in plugin files as records.  When multiple mods modify the same records, only the last loaded mod's changes get used by the game (with some exceptions).  This is known as the rule of one.  Many plugin patches combine the changes of multiple mods to resolve conflicts, but there is no way to create and distribute patches for every possible combination of conflicting mods.  This is where tools like Mator Smash come in.  Mator Smash allows for conflict resolution patches to be generated following rules, known as "Smash Settings".  This allows users to quickly and efficiently combine the edits of multiple mods.

## intended usage
Use Mator Smash to generate a patch, then verify the changes in the patch in xEdit.  Fix any conflicts that were not resolved correctly.  Smashed patches should be usable without a manual verification step, but can in certain rare cases lead to crashes/unintended behavior in game.  If you run into issues please report them [here](https://github.com/matortheeternal/smash/issues).  You can safely disable or delete your smashed patch at any time.

# resources
If you're looking for support or want to contribute, join the [Modding Tools discord server](https://discord.gg/GUfRdpT).

You can find additional information and discussion on the [Nexus Mods](https://www.nexusmods.com/skyrim/mods/90987) mod page, in the [STEP forum topic](http://forum.step-project.com/topic/6936-wip-mator-smash/), and in the [Nexus Mods forum topic](https://forums.nexusmods.com/index.php?/topic/3707015-wip-mator-smash-the-conflict-resolution-revolution/).

================================================
FILE: design/code snippets/GetMasterElement.pas
================================================
{for j := 0 to ElementCount(ae) - 1 do begin
  ne := ebi(ae, j);
  if (SortKey(ne, false) = sk) then begin
    Result := ne;
    break;
  end;
end;}

{for j := 0 to ElementCount(ae) - 1 do begin
  ne := ebi(ae, j);
  if (gav(ne) = sk) then begin
    Result := ne;
    break;
  end;
end;}

function ElementByKey(e: IwbElement; key: string; bUseSortKey: boolean): IwbElement;
var
  i: Integer;
  c: IwbContainerElementRef;
begin
  if not Supports(e, IwbContainerElementRef, c) then 
    exit;
  
  // loop through children elements
  for i := 0 to Pred(c.ElementCount) do begin
    element := c.Elements[i];
    // get sort key if bUseSortKey, else get values key
    if bUseSortKey then
      eKey := element.SortKey[false]
    else
      eKey := GetAllValues(element);
    // if keys match result is current element
    if eKey = key then begin
      Result := element;
      break;
    end;
  end;
end;

function GetMasterElement(src, se: IwbElement; dstRec: IwbMainRecord): IwbElement;
var
  i: integer;
  path, key: string;
  mstRec, ovr: IwbMainRecord;
  mst: IwbElement;
  sorted: boolean;
begin
  Result := nil;
  mstRec := MasterOrSelf(dstRec);
  path := IndexedPath(src);
  bSorted := IsSorted(src);
  
  // if sorted, use SortKey, else use GetAllValues
  if bSorted then 
    key := se.SortKey[false]
  else
    key := GetAllValues(se);
    
  // debug message
  if debugGetMaster then 
    Tracker.Write('  Called GetMasterElement at path '+p+' looking for Key '+key);
    
  // loop from override 0 to the second to last override
  // last override is in our patch, we don't want to process that one
  for i := 0 to mstRec.OverrideCount - 2 do begin
    ovr := mst.Overrides[i];
    mst := ElementByIndexedPath[(mstRec, p);
    Result := ElementByKey(mst, key, bSorted);
    
    // break if we found a subrecord matching the sortkey
    if Result <> nil then
      break;
  end;
end;


================================================
FILE: design/code snippets/Mator Smash v0.9.pas
================================================
{
  Mator Smash v0.9.6
  created by matortheeternal
  
  * DESCRIPTION *
  This script will make a patch similar to a bashed patch.
}

unit smash;

uses mteFunctions;

const
  vs = 'v0.9.6';
  settingsPath = scriptsPath + 'smash\settings\';
  dashes = '-----------------------------------------------------------';
  // these booleans control logging
  debugGetMaster = false;
  debugArrays = false;
  listOverrides = false;
  showChanges = false;
  showTraversal = false;
  showSkips = false;
  showTypeStrings = false;
  showRecTimes = false;
  verbose = false;
  disableStyles = false;
  // maximum records to be smashed
  maxRecords = 100000;
  splitChar = '#13';
 
var
  slRecords, slSettings, slOptions, slFiles, slSubrecords, 
  slGlobalSubrecords, recordTree, subrecordTree, include: TStringList;
  lstSettings: TList;
  userFile: IInterface;
  global_records, global_subrecords, global_recordMode, 
  global_subrecordMode, global_setting: string;
  makeNewLine: boolean;
  AssetPath: string;
  checkboxImages: TCustomImageList;
  


{===========================================================}
{ SETTING FORM }

const
  cChecked = 1;
  cUnChecked = 2;
  cPartiallyChecked = 3;

var
  sfrm: TForm;
  meInclude, meSubrecords: TMemo;
  tv: TTreeView;
  btnOk, btnCancel: TButton;
  

{
  SetChildren
  Sets the StateIndex attribute of all the children of @node 
  to @state.  Uses recursion.
}
procedure SetChildren(node: TTreeNode; state: Integer);
var
  tmp: TTreeNode;
begin
  // exit if we don't have a node to work with
  if not Assigned(node) then exit;

  // loop through children setting StateIndex to state
  // if child has children, recurse into that child
  tmp := node.getFirstChild;
  while Assigned(tmp) do begin
    tmp.StateIndex := state;
    if tmp.HasChildren then
      SetChildren(tmp, state);
    tmp := tmp.getNextSibling;
  end;
end;

{
  UpdateParent
  Calculates and sets the StateIndex attribute for @node based
  on the StateIndex values of its children.  Uses recursion to 
  update parents of the parent that was updated.
}
procedure UpdateParent(node: TTreeNode);
var
  tmp: TTreeNode;
  state: Integer;
begin
  // exit if we don't have a node to work with
  if not Assigned(node) then exit;

  // parent state is checked if all siblings are checked
  state := cChecked;
  tmp := node.getFirstChild;
  while Assigned(tmp) do begin
    if tmp.StateIndex <> cChecked then begin
      state := cPartiallyChecked;
      break;
    end;
    tmp := tmp.getNextSibling;
  end;

  // parent state is unchecked if all siblings are unchecked
  if state = cPartiallyChecked then begin
    state := cUnChecked;
    tmp := node.getFirstChild;
    while Assigned(tmp) do begin
      if tmp.StateIndex <> cUnChecked then begin
        state := cPartiallyChecked;
        break;
      end;
      tmp := tmp.getNextSibling;
    end;
  end;

  // set state, recurse to next parent
  node.StateIndex := state;
  tmp := node.Parent;
  UpdateParent(tmp);
end;

{
  CheckBoxManager
  Manages checkboxes in the TTreeView.  Changes the StateIndex 
  of the checkbox associated with @node.  Uses SetChildren and
  UpdateParent.  Called by tvClick and tvKeyDown.
}
procedure CheckBoxManager(node: TTreeNode);
begin
  // exit if we don't have a node to work with
  if not Assigned(node) then exit;
  
  // if unchecked or partially checked, set to checked and
  // set all children to checked, update parents
  if (node.StateIndex = cUnChecked)
  or (node.StateIndex = cPartiallyChecked) then begin
    node.StateIndex := cChecked;
    UpdateParent(node.Parent);
    SetChildren(node, cChecked);
  end
  // if checked, set to unchecked and set all children to
  // unchecked, update parents
  else if node.StateIndex = cChecked then begin
    node.StateIndex := cUnChecked;
    UpdateParent(node.Parent);
    SetChildren(node, cUnChecked);
  end;
end;

{
  tvClick
  Event handler for when the user clicks anywhere in the 
  TreeView.  If the user clicks on a checkbox it calls 
  CheckBoxManager to toggle the state of the selected
  checkbox.
}
procedure tvClick(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  HT: THitTests;
begin
  HT := tv.GetHitTestInfoAt(X, Y);
  if (HT - [htOnStateIcon] <> HT) then
    CheckBoxManager(tv.Selected);
end;

{
  tvKeyDown
  Event handler for when the user presses a key while the 
  TreeView is focused.  If the user presses space we call 
  CheckBoxManager to toggle the state of the selected 
  checkbox.
}
procedure tvKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if (Key = VK_SPACE) and Assigned(tv.Selected) then
    CheckBoxManager(tv.Selected);
end;

{
  tvExpanding
  Event handler for when the user expands a node in the
  TreeView.  If we haven't loaded the subrecords for the
  record represented by @node, we call LoadNodes.
}
procedure tvExpanding(Sender: TObject; node: TTreeNode; 
  var AllowExpansion: Boolean);
var
  i: integer;
begin
  if not Assigned(node.getFirstChild) then exit;
  
  // if we haven't loaded subrecord data yet, attempt to
  // load it from the subrecord stringlist
  if node.getFirstChild.Text = 'Elements' then begin
    // find record signature in subrecords stringlist
    // exit if not found
    i := subrecordTree.IndexOf(node.Text);
    if i = -1 then exit;
    
    // load nodes from the subrecords stringlist
    // starting at the first subrecord
    LoadNodes(subrecordTree, tv, node, i + 1, 2);
    
    // delete 'Elements' placeholder node
    node.getFirstChild.Delete;
  end;
end;

{
  LeadingSpaces
  Calculates the number of leading spaces in a PChar string
  and returns it as an integer.
}
function LeadingSpaces(var s: PChar): integer;
var
  i: integer;
begin
  Result := 0;
  i := 1;
  while (true) do begin
    if s[i] = ' ' then 
      Inc(Result)
    else
      exit;
    Inc(i);
  end;
end;

{
  LoadNodes
  Loads nodes from @sl into @tv as children of @node.  Starts
  at index @i in the stringlist and adds children which have
  leading spaces matching @cws.  If there are more leading 
  spaces than @cws, we use recursion to add the list item as
  a child of the current list item @curNode.  If there are
  fewer leading spaces than @cws we exit.
}
procedure LoadNodes(var sl: TStringList; tv: TTreeView; node: TTreeNode; 
  var i: integer; cws: integer);
var
  lws: integer;
  p: PChar;
  curNode: TTreeNode;
begin
  curNode := node;
  while (true) do begin
    // exit if we reached the end of the stringlist
    if i > sl.Count - 1 then exit; 
    p := sl[i];
    lws := LeadingSpaces(p);
    
    // if lws matches cws, add as child of current node
    // (we're on the right level)
    if lws = cws then begin
      curNode := tv.Items.AddChild(node, Trim(sl[i]));
      curNode.StateIndex := node.StateIndex;
    end 
    // if leading spaces of the current item exceeds cws,
    // recurse to add as child of the last added node
    // (we need to go down a level)
    else if lws > cws then begin
      LoadNodes(sl, tv, curNode, i, lws);
      continue;
    end
    // if cws exceeds lws, exit
    // (we need to go up a level)
    else
      exit;
    
    // go to next item in list
    Inc(i);
  end;
end;

{
  FindNode
  Finds a node matching @s as a child of @node.
}
function FindNode(node: TTreeNode; const s: string): TTreeNode;
var
  tmp: TTreeNode;
begin
  Result := nil;
  tmp := node.getFirstChild;
  while (Assigned(tmp)) do begin
    if (tmp.Text = s) then begin
      Result := tmp;
      exit;
    end;
    tmp := tmp.getNextSibling;
  end;
end;

{
  DisableNodes
  Disables nodes from @sl in @tv found as children of @node.  
  Starts at index @i in the stringlist and locates children 
  which have leading spaces matching @cws.  If there are more 
  leading spaces than @cws, we use recursion to find the list
  item in the current item @curNode.  If there are fewer leading 
  spaces than @cws we exit.
}
procedure DisableNodes(var sl: TStringList; tv: TTreeView; node: TTreeNode; 
  var i: integer; cws: integer);
var
  lws: integer;
  p: PChar;
  curNode: TTreeNode;
begin
  curNode := node;
  while (true) do begin
    // exit if we reached the end of the stringlist
    if i > sl.Count - 1 then exit; 
    p := sl[i];
    lws := LeadingSpaces(p);
    
    // if lws matches cws, find and disable
    if lws = cws then begin
      curNode := FindNode(node, Trim(sl[i]));
      if not Assigned(curNode) then begin
        Inc(i);
        continue;
      end;
      if i + 1 = sl.Count then begin
        curNode.StateIndex := cUnChecked;
      end
      else begin
        p := sl[i+1];
        lws := LeadingSpaces(p);
        if lws > cws then begin
          tvExpanding(nil, curNode, true);
          curNode.StateIndex := cPartiallyChecked;
        end
        else begin
          curNode.StateIndex := cUnChecked;
        end;
      end;
    end 
    // if leading spaces of the current item exceeds cws,
    // recurse to find in the last added node
    // (we need to go down a level)
    else if lws > cws then begin
      DisableNodes(sl, tv, curNode, i, lws);
      continue;
    end
    // if cws exceeds lws, exit
    // (we need to go up a level)
    else
      exit;
    
    // go to next item in list
    Inc(i);
  end;
end;

{
  MakeBold
  Changes the style of @lbl to bold.
}
procedure MakeBold(lbl: TLabel);
begin
  if not disableStyles then begin
    lbl.WordWrap := false;
    lbl.Font.Style := lbl.Font.Style + [fsBold];
  end;
end;

{
  SettingFormResize
  Event to fire when the setting form is resized
}
procedure SettingFormResize(Sender: TObject);
begin
  tv.Width := sfrm.Width - 48;
  tv.Height := sfrm.Height - 155;
  btnOk.Top := sfrm.Height - 86;
  btnOk.Left := sfrm.Width div 2 - btnOk.Width - 8;
  btnCancel.Top := btnOk.Top;
  btnCancel.Left := btnOk.Left + btnOk.Width + 16;
end;

{
  CreateIncludeList
  Recursively traverses a TreeView starting at @node adding node 
  text properties to @sl, with @depth concatenated before each text 
  item.
}
procedure CreateIncludeList(var sl: TStringList; node: TTreeNode; depth: string);
var
  tmp: TTreeNode;
begin
  if (not node.HasChildren) then exit;
  
  tmp := node.getFirstChild;
  while (Assigned(tmp)) do begin
    if (tmp.StateIndex = cUnChecked) then
      sl.Add(depth + tmp.Text)
    else if (tmp.HasChildren) and (tmp.StateIndex = cPartiallyChecked) then begin
      sl.Add(depth + tmp.Text);
      CreateIncludeList(sl, tmp, depth + '  ');
    end;
    tmp := tmp.getNextSibling;
  end;
end;

{
  SettingForm
  Used to create or edit setting presets.
}
procedure SettingForm(Sender: TObject);
var
  lblName, lblRecords, lblSubrecords: TLabel;
  edName: TEdit;
  ini, template: TMemIni;
  usingTemplate: boolean;
  caption: string;
  node: TTreeNode;
  ndx: integer;
begin
  // assign template
  include := TStringList.Create;
  caption := TButton(Sender).Caption;
  usingTemplate := caption <> 'New setting';
  if lst.ItemIndex > -1 then
    template := TMemIniFile(lstSettings[slSettings.IndexOf(lst.Items[lst.ItemIndex])])
  else
    usingTemplate := false;
  
  sfrm := TForm.Create(nil);
  try
    // set up form
    sfrm.Width := 400;
    sfrm.Height := 600;
    sfrm.Position := poScreenCenter;
    sfrm.Caption := 'Create new Smash Setting';
    sfrm.Constraints.MinHeight := 400;
    sfrm.Constraints.MinWidth := 286;
    
    // make label and edit for name
    lblName := cLabel(sfrm, sfrm, 16, 16, 0, 0, 'Name: ', '');
    edName := cEdit(sfrm, sfrm, lblName.Top, lblName.Left + lblName.Width + 8, 0, 200, '', '');
    
    // make tree view
    tv := TTreeView.Create(sfrm);
    tv.Parent := sfrm;
    tv.Left := lblName.Left;
    tv.Top := lblName.Top + lblName.Height + 20;
    tv.Width := sfrm.Width - 48;
    tv.Height := sfrm.Height - 155;
    tv.Indent := 19;
    tv.ReadOnly := true;
    tv.StateImages := checkboxImages;
    tv.OnMouseDown := tvClick;
    tv.OnKeyDown := tvKeyDown;
    tv.OnExpanding := tvExpanding;
    
    // construct ok and cancel buttons
    btnOk := TButton.Create(sfrm);
    btnOk.Parent := sfrm;
    btnOk.Left := sfrm.Width div 2 - btnOk.Width - 8;
    btnOk.Top := sfrm.Height - 86;
    btnOk.Caption := 'OK';
    btnOk.ModalResult := mrOK;
    
    btnCancel := TButton.Create(sfrm);
    btnCancel.Parent := sfrm;
    btnCancel.Left := btnOk.Left + btnOk.Width + 16;
    btnCancel.Top := btnOk.Top;
    btnCancel.Caption := 'Cancel';
    btnCancel.ModalResult := mrCancel;
    
    // load record nodes
    node := tv.Items.Add(nil, 'Records');
    if usingTemplate then
      node.StateIndex := cChecked
    else 
      node.StateIndex := cUnChecked;
    LoadNodes(recordTree, tv, node, 0, 0);
    
    // if using template, load values from it for form
    if usingTemplate then begin
      edName.Caption := template.ReadString('Setting', 'Name', '');
      if caption = 'Copy setting' then begin
        sfrm.Caption := 'Copy Smash Setting';
        edName.Caption := 'Copy of '+edName.Caption;
      end
      else if caption = 'Edit setting' then begin
        sfrm.Caption := 'Edit Smash Setting';
        edName.Enabled := false;
      end;
      
      include.LoadFromFile(settingsPath + edName.Caption + '.ini');
      ndx := include.IndexOf('[Tree]') + 1;
      if (ndx < include.Count) then begin
        if (include[ndx] <> '') then begin
          DisableNodes(include, tv, node, ndx, 0);
          node.StateIndex := cPartiallyChecked;
        end;
      end;
    end;
    
    // set onresize event
    sfrm.OnResize := SettingFormResize;
    
    // if user clicks ok, save to ini and update lists
    if sfrm.ShowModal = mrOk then begin
      ini := TMemIniFile.Create(settingsPath + edName.Caption + '.ini');
      ini.WriteString('Setting', 'Name', edName.Caption);
      ini.UpdateFile;
      
      include.LoadFromFile(settingsPath + edName.Caption + '.ini');
      ndx := include.IndexOf('[Tree]');
      if (ndx = -1) then
        include.Add('[Tree]')
      else begin
        Inc(ndx);
        while (include.Count > ndx) do
          include.Delete(ndx);
      end;
      CreateIncludeList(include, node, '');
      include.SaveToFile(settingsPath + edName.Caption + '.ini');
      
      if (slSettings.IndexOf(edName.Caption) = -1) then begin
        lstSettings.Add(ini);
        slSettings.Add(edName.Caption);
        lst.Items.Add(edName.Caption);
      end
      else
        lstSettings[slSettings.IndexOf(edName.Caption)] := ini;
    end;
  finally
    sfrm.Free;
  end;
end;


{===========================================================}
{ SETTING MANAGER FORM }

var
  btnDetails, btnEdit, btnCopy, btnDel: TButton;
  gear: TPicture;
  lst: TListBox;

  
{
  ToggleButtons
  Toggles btnEdit, btnCopy, btnDelete.
}
procedure ToggleButtons(Sender: TObject);
var
  b: boolean;
begin
  b := (TListBox(Sender).ItemIndex > -1);
  btnEdit.Enabled := b; btnCopy.Enabled := b; btnDel.Enabled := b;
end;

{
  DeleteSetting
  Deletes the currently selected setting.
}
procedure DeleteSetting(Sender: TObject);
var
  s: string;
begin
  if lst.ItemIndex > -1 then begin
    s := lst.Items[lst.ItemIndex];
    lstSettings.Delete(slSettings.IndexOf(s));
    slSettings.Delete(slSettings.IndexOf(s));
    lst.Items.Delete(lst.ItemIndex);
    lst.ItemIndex := -1;
    DeleteFile(settingsPath + s + '.ini');
  end;
end;

{
  UpdateSettings
  Updates the setting comboboxes for OptionsForm
}
procedure UpdateSettings;
var
  i, ndx: integer;
  cb: TComboBox;
  s: string;
begin
  for i := 0 to pnlCount - 1 do begin
    cb := TComboBox(pnlArray[i].Components[1]);
    s := cb.Items[cb.ItemIndex];
    cb.Items.Text := slSettings.Text;
    if cb.Items.IndexOf(s) > -1 then
      cb.ItemIndex := cb.Items.IndexOf(s)
    else
      cb.ItemIndex := 0;
  end;
  
  // update global setting combobox
  s := gscb.Items[gscb.ItemIndex];
  gscb.Items.Text := slSettings.Text;
  if gscb.Items.IndexOf(s) > -1 then
    gscb.ItemIndex := gscb.Items.IndexOf(s)
  else
    gscb.ItemIndex := 0;
end;

{
  SettingManager
  Used by the user to view, edit, and create settings.
}
procedure SettingManager;
var
  ofrm: TForm;
  i, h: integer;
  btnNew, btnOk : TButton;
begin
  ofrm := TForm.Create(nil);
  try
    ofrm.Caption := 'Advanced Options';
    ofrm.Width := 400;
    ofrm.Position := poScreenCenter;
    ofrm.Height := 300;
    
    h := slSettings.Count * 15 + 85;
    if h > 500 then
      h := 500;
    if h > ofrm.Height then
      ofrm.Height := h;
    
    // list box of settings
    lst := TListBox.Create(ofrm);
    lst.Parent := ofrm;
    lst.Top := 8;
    lst.Left := 8;
    lst.Height := ofrm.Height - 105;
    lst.Width := ofrm.Width - 145;
    for i := 0 to slSettings.Count - 1 do
      lst.Items.Add(slSettings[i]);
    lst.OnClick := ToggleButtons;
    
    // new setting button
    btnNew := cButton(ofrm, ofrm, 8, lst.Left + lst.Width + 8, 0, 100, 'New setting');
    btnNew.OnClick := SettingForm;
    // edit setting button
    btnEdit := cButton(ofrm, ofrm, btnNew.Top + btnNew.Height + 8, btnNew.Left, 0, 100, 'Edit setting');
    btnEdit.OnClick := SettingForm;
    btnEdit.Enabled := false;
    // copy setting button
    btnCopy := cButton(ofrm, ofrm, btnEdit.Top + btnEdit.Height + 8, btnNew.Left, 0, 100, 'Copy Setting');
    btnCopy.OnClick := SettingForm;
    btnCopy.Enabled := false;
    // delete setting button
    btnDel := cButton(ofrm, ofrm, btnCopy.Top + btnCopy.Height + 8, btnNew.Left, 0, 100, 'Delete setting');
    btnDel.OnClick := DeleteSetting;
    btnDel.Enabled := false;
    // OK button
    btnOk := cButton(ofrm, ofrm, ofrm.Height - 80, ofrm.Width div 2 - 40, 0, 0, 'OK');
    btnOk.ModalResult := mrOk;
    
    ofrm.ShowModal;
  finally
    ofrm.free;
  end;
  UpdateSettings;
end;


{===========================================================}
{ PLUGIN DETAILS FORM }


{
  GetGroupOverrides
}
function GetGroupOverrides(f: IInterface): string;
var
  i: integer;
  e: IInterface;
begin
  for i := 0 to ElementCount(f) - 1 do begin
    e := ebi(f, i);
    if Signature(e) = 'TES4' then continue;
    Result := Result + GroupSignature(e) + ': '+IntToStr(OverrideRecordCount(e))+' overrides'#13#10;
  end;
end;

{
  PluginDetails
  Form which shows advanced details on a plugin
}
procedure PluginDetails(Sender: TObject);
var
  f, e: IInterface;
  i: integer;
  fn, author, records, overrides, desc, masters, groups: string;
  pfrm: TForm;
  lbl: TLabel;
  sb: TScrollBox;
  memo: TMemo;
begin
  // find file
  fn := TLabel(Sender).Caption;
  fn := Copy(fn, Pos(']', fn) + 2, Length(fn));
  f := FileByName(fn);
  
  // get data
  author := geev(ebi(f, 0), 'CNAM');
  records := IntToStr(RecordCount(f));
  overrides := IntToStr(OverrideRecordCount(f));
  desc := geev(ebi(f, 0), 'SNAM');
  e := ebn(ebi(f, 0), 'Master Files');
  for i := 0 to ElementCount(e) - 1 do
    masters := masters + geev(ebi(e, i), 'MAST') + #13#10;
  groups := GetGroupOverrides(f);
    
  // display form
  pfrm := TForm.Create(nil);
  try
    pfrm.Caption := fn;
    pfrm.Width := 400;
    pfrm.Height := 600;
    pfrm.Position := poScreenCenter;
    
    lbl := cLabel(pfrm, pfrm, 8, 8, 0, 150, 'Filename:', '');
    MakeBold(lbl);
    lbl := cLabel(pfrm, pfrm, lbl.Top, 160, 0, 200, fn, '');
    lbl := cLabel(pfrm, pfrm, lbl.Top + 22, 8, 0, 150, 'Author:', '');
    MakeBold(lbl);
    lbl := cLabel(pfrm, pfrm, lbl.Top, 160, 0, 200, author, '');
    lbl := cLabel(pfrm, pfrm, lbl.Top + 22, 8, 0, 150, 'Number of records:', '');
    MakeBold(lbl);
    lbl := cLabel(pfrm, pfrm, lbl.Top, 160, 0, 200, records, '');
    lbl := cLabel(pfrm, pfrm, lbl.Top + 22, 8, 0, 150, 'Number of overrides:', '');
    MakeBold(lbl);
    lbl := cLabel(pfrm, pfrm, lbl.Top, 160, 0, 200, overrides, '');
    lbl := cLabel(pfrm, pfrm, lbl.Top + 22, 8, 0, 150, 'Description:', '');
    MakeBold(lbl);
    memo := cMemo(pfrm, pfrm, lbl.Top + 22, 16, 100, 348, true, true, ssVertical, desc);
    lbl := cLabel(pfrm, pfrm, memo.Top + memo.Height + 16, 8, 0, 150, 'Masters:', '');
    MakeBold(lbl);
    memo := cMemo(pfrm, pfrm, lbl.Top + 22, 16, 100, 348, true, true, ssVertical, masters);
    lbl := cLabel(pfrm, pfrm, memo.Top + memo.Height + 16, 8, 0, 150, 'Record groups:', '');
    MakeBold(lbl);
    memo := cMemo(pfrm, pfrm, lbl.Top + 22, 16, 150, 348, true, true, ssVertical, groups);
    
    pfrm.ShowModal;
  finally
    pfrm.Free;
  end;
end;


{===========================================================}
{ OPTIONS FORM }

var
  frm: TForm;
  gscb: TComboBox;
  pnlArray: Array[0..255] of TPanel;
  pnlCount: integer;

  
{
  OptionsForm
  Form from which the user can access the setting manager,
  plugin details, and set the settings to be used when smashing
  the loaded plugins.
}
function OptionsForm: boolean;
var
  i, height, m: integer;
  btnSmash, btnCancel: TButton;
  optionslbl, fnlbl, gslbl: TLabel;
  cb: TComboBox;
  f: IInterface;
  fn, author, s: string;
  imgOptions: TImage;
  pnl: TPanel;
  holder: TObject;
  sb: TScrollBar;
begin
  Result := false;
  frm := TForm.Create(nil);
  try
    frm.Caption := 'Mator Smash Options';
    frm.Width := 550;
    frm.Position := poScreenCenter;
    frm.Height := 400;
    for i := 0 to FileCount - 1 do begin
      f := FileByIndex(i);
      fn := GetFileName(f);
      author := geev(ebi(f, 0), 'CNAM');
      if (Pos(fn, bethesdaFiles) > 0) or (Pos('Mator Smash', author) > 0) then Continue;
      Inc(m);
    end;
    height := m*40 + 170;
    if height > (Screen.Height - 100) then begin
      frm.Height := Screen.Height - 100;
      sb := TScrollBox.Create(frm);
      sb.Parent := frm;
      sb.Height := Screen.Height - 210;
      sb.Width := frm.Width - 20;
      sb.Align := alTop;
      holder := sb;
    end
    else begin
      frm.Height := height;
      holder := frm;
    end;
    
    optionslbl := cLabel(frm, holder, 8, 8, 0, 450, 
      'Set the options you want to use for smashing the following plugins:', '');
    
    pnlCount := 0;
    for i := 0 to FileCount - 1 do begin
      f := FileByIndex(i);
      fn := GetFileName(f);
      author := geev(ebi(f, 0), 'CNAM');
      if Pos(fn, bethesdaFiles) > 0 then
        continue;
      if Pos('Mator Smash', author) > 0 then
        continue;
      
      pnlArray[pnlCount] := TPanel.Create(frm);
      pnlArray[pnlCount].Parent := holder;
      pnlArray[pnlCount].Left := 0;
      pnlArray[pnlCount].Top := 30 + pnlCount*40;
      pnlArray[pnlCount].Width := holder.Width - 25;
      pnlArray[pnlCount].BevelOuter := bvNone;
      pnlArray[pnlCount].BevelInner := bvNone; // or bvLowered
      pnlArray[pnlCount].BorderStyle := bsNone; // or bsSingle
      
      fnlbl := cLabel(pnlArray[pnlCount], pnlArray[pnlCount], 14, 24, 0, 0, '['+IntToHex(i - 1, 2)+'] '+fn, '');
      fnlbl.OnClick := PluginDetails;
      MakeBold(fnlbl);
      
      cb := TComboBox.Create(pnlArray[pnlCount]);
      cb.Parent := pnlArray[pnlCount];
      cb.Style := csDropDownList;
      cb.Items := slSettings;
      cb.ItemIndex := 0;
      if slSettings.IndexOf('default') > -1 then
        cb.ItemIndex := slSettings.IndexOf('default');
      cb.Top := 12;
      cb.Width := 150;
      cb.Left := holder.Width - cb.Width - 40;
      
      slFiles.Add(fn);
      Inc(pnlCount);
    end;
    
    // create global setting controls
    gslbl := cLabel(frm, holder, pnlArray[pnlCount - 1].Top + pnlArray[pnlCount - 1].Height + 16,
      optionslbl.Left, 0, 70, 'Global setting: ', '');
    gscb := TComboBox.Create(frm);
    gscb.Parent := holder;
    gscb.Top := gslbl.Top;
    gscb.Left := gslbl.Left + gslbl.Width + 16;
    gscb.Width := 150;
    gscb.Style := csDropDownList;
    gscb.Items := slSettings;
    gscb.ItemIndex := 0;
    if slSettings.IndexOf('default') > -1 then
      gscb.ItemIndex := slSettings.IndexOf('default');
    
    pnl := TPanel.Create(frm);
    pnl.Parent := frm;
    pnl.BevelOuter := bvNone;
    pnl.Align := alBottom;
    pnl.Height := 50;
    
    imgOptions := cImage(pnl, pnl, pnl.Height - 40, frm.Width - 50, 24, 24, gear, 'Advanced Options');
    imgOptions.OnClick := SettingManager;
    
    // create ok/cancel buttons
    btnSmash := cButton(frm, pnl, pnl.Height - 40, frm.Width div 2 - 88, 0, 0, 'Smash!');
    btnSmash.ModalResult := mrOk;
    btnCancel := cButton(frm, pnl, btnSmash.Top, btnSmash.Left + btnSmash.Width + 16, 0, 0, 'Cancel');
    btnCancel.ModalResult := mrCancel;
    
    if frm.ShowModal = mrOk then begin
      for i := 0 to pnlCount - 1 do begin
        s := TComboBox(pnlArray[i].Components[1]).Text;
        slOptions.Add(s);
      end;
      global_setting := gscb.Text;
      Result := true;
    end;
  finally
    frm.Free;
  end;
end;


{===========================================================}
{ SMASHING METHODS }

var
  pb: TProgressBar;
  memo: TMemo;
  lbl: TLabel;


{
  LogMessage
  Adds @msg to the log stringlist
}
procedure LogMessage(msg: string);
begin
  memo.Lines.add(msg);
  Application.processmessages;
end;

{
  GetMasterElement
  Gets the first instance of an element (the master)
}
function GetMasterElement(src, se, dstrec: IInterface): IInterface;
var
  i, j, ndx: integer;
  p, sk: string;
  ovr, ae, ne, mst: IInterface;
  sorted: boolean;
begin
  Result := nil;
  mst := MasterOrSelf(dstrec);
  p := IndexedPath(src);
  sk := SortKey(se, false);
  sorted := not (sk = '');
  // if sorted, look for an element matching sort key
  if sorted then begin
    if debugGetMaster then LogMessage('  Called GetMasterElement at path '+p+' looking for SortKey '+SortKey(se, false));
    // loop from override 0 to the second to last override
    for i := 0 to OverrideCount(mst) - 2 do begin
      ovr := OverrideByIndex(mst, i);
      ae := ebp(mst, p);
      for j := 0 to ElementCount(ae) - 1 do begin
        ne := ebi(ae, j);
        if (SortKey(ne, false) = sk) then begin
          Result := ne;
          break;
        end;
      end;
      // break if we found a subrecord matching the sortkey
      if Result <> nil then
        break;
    end;
  end 
  // if unsorted, look for the element using gav
  else begin
    sk := gav(se);
    if debugGetMaster then LogMessage('  Called GetMasterElement at path '+p+' looking for '+sk);
    ae := ebp(mst, p);
    for i := 0 to OverrideCount(mst) - 1 do begin
      ovr := OverrideByIndex(mst, i);
      ae := ebp(ovr, p);
      for j := 0 to ElementCount(ae) - 1 do begin
        ne := ebi(ae, j);
        if (gav(ne) = sk) then begin
          Result := ne;
          break;
        end;
      end;
    end;
  end;
end;
  
{
  nbsOverrideCount
  Non-Bethesda Override Count
}
function nbsOverrideCount(r: IInterface): integer;
var
  i: integer;
  fn: string;
begin
  Result := 0;
  for i := 0 to OverrideCount(r) - 1 do begin
    fn := GetFileName(GetFile(OverrideByIndex(r, i)));
    if Pos(fn, bethesdaFiles) = 0 then
      Result := Result + 1;
  end;
end;

{
  BuildSortKeyList
  Puts the sort keys of elements in a stringlist
}
procedure BuildSortKeyList(element: IInterface; var sl: TStringList);
var
  i, n: integer;
  childElement: IInterface;
  sk, skAdj: string;
begin
  for i := 0 to ElementCount(element) - 1 do begin
    childElement := ebi(element, i);
    sk := SortKey(childElement, false);
    skAdj := sk;
    n := 0;
    while sl.IndexOf(skAdj) > -1 do begin
      Inc(n);
      skAdj := sk + '-' + IntTostr(n);
    end;
    if debugArrays and (n > 0) then LogMessage('    Adjusted SortKey: '+skAdj);
    sl.Add(skAdj);
  end;
end;

{
  MergeSortedArray
  Merges sorted array elements
}
procedure MergeSortedArray(mst, src, dst, dstrec: IInterface; depth: string; ini: TMemIniFile);
var
  i, m_ndx, s_ndx, d_ndx, n: integer;
  me, se, de, ne: IInterface;
  slMst, slDst, slSrc: TStringList;
  useValues: boolean;
  dts, ets, sk: string;
begin
  // Step 1: build lists of elements in each array for easy comparison
  slMst := TStringList.Create;
  slSrc := TStringList.Create;
  slDst := TStringList.Create;
  slDst.Sorted := true;
  BuildSortKeyList(mst, slMst);
  BuildSortKeyList(src, slSrc);
  BuildSortKeyList(dst, slDst);
  
  // Step 2: Remove elements that are in mst and dst, but missing from src
  for i := 0 to slMst.Count - 1 do begin
    s_ndx := slSrc.IndexOf(slMst[i]);
    d_ndx := slDst.IndexOf(slMst[i]);
    
    if (s_ndx = -1) and (d_ndx > -1) then begin
      if debugArrays then LogMessage('      > Removing element '+Path(ebi(dst, d_ndx))+' with key: '+slDst[d_ndx]);
      RemoveElement(dst, ebi(dst, d_ndx));
      slDst.Delete(d_ndx);
    end;
  end;
  
  // Step 3: Copy array elements in src that aren't in mst.
  for i := 0 to slSrc.Count - 1 do begin
    d_ndx := slDst.IndexOf(slSrc[i]);
    m_ndx := slMst.IndexOf(slSrc[i]);
    
    se := ebi(src, i);
    dts := DefTypeString(se);
    ets := ElementTypeString(se);
    if (d_ndx = -1) and (m_ndx = -1) then begin
      if debugArrays then LogMessage('      > Adding element '+IntToStr(i)+' at '+Path(dst)+' with key: '+slSrc[i]);
      ne := ElementAssign(dst, HighInteger, se, false);
      if debugArrays then LogMessage('      > '+gav(ne));
      slDst.Add(slSrc[i]);
    end
    // Step 3.5: If array element is in dst and has subelements, traverse it.
    else if (d_ndx > -1) and ((dts = 'dtStruct') or (ets = 'etSubRecordArray')) then begin
	    if showTraversal then LogMessage('      > Traversing element '+Path(se)+' with key: '+slSrc[i]);
      if showTraversal and debugArrays then LogMessage('      > Source Element: '+gav(se)+
        #13#10'      > Destination Element: '+gav(ebi(dst, d_ndx)));
      try
        rcore(se, GetMasterElement(src, se, dstrec), ebi(dst, d_ndx), dstrec, depth + '    ', ini);
      except on x : Exception do begin
          LogMessage('      !! rcore exception: '+x.Message);
        end;
      end;
    end
    else if (d_ndx > -1) and (ets = 'etSubRecordStruct') then begin
	    if showTraversal then LogMessage('      > Traversing element '+Path(se)+' with key: '+slSrc[i]);
      if showTraversal and debugArrays then LogMessage('      > Source Element: '+gav(se)+
        #13#10'      > Destination Element: '+gav(ebi(dst, d_ndx)));
      try
        rcore(se, GetMasterElement(src, se, dstrec), ebi(dst, d_ndx), dstrec, depth + '    ', ini);
      except on x : Exception do begin
          LogMessage('      !! rcore exception: '+x.Message);
        end;
      end;
    end;
  end;
  
  // Step 4: Free lists.
  slMst.Free;
  slSrc.Free;
  slDst.Free;
end;

{
  BuildElementList
  Puts the values of elements in a stringlist
}
procedure BuildElementList(element: IInterface; var sl: TStringList);
var
  i, n: integer;
  childElement: IInterface;
  values, valuesAdj: string;
begin
  for i := 0 to ElementCount(element) - 1 do begin
    childElement := ebi(element, i);
    values := gav(childElement);
    valuesAdj := values;
    n := 0;
    while (sl.IndexOf(valuesAdj) > -1) do begin
      Inc(n);
      valuesAdj := values + IntToStr(n);
    end;
    sl.Add(valuesAdj);
  end;
end;

{
  MergeUnsortedArray
  Merges unsorted array elements
}
procedure MergeUnsortedArray(mst, src, dst, dstrec: IInterface; depth: string; ini: TMemIniFile);
var
  i, m_ndx, s_ndx, d_ndx: integer;
  me, se, de: IInterface;
  slMst, slSrc, slDst: TStringList;
  useValues: boolean;
  dts, ets: string;
begin
  // Step 1: build lists of elements in each array for easy comparison
  slMst := TStringList.Create;
  slSrc := TStringList.Create;
  slDst := TStringList.Create;
  BuildElementList(mst, slMst);
  BuildElementList(src, slSrc);
  BuildElementList(dst, slDst);
  
  // Step 2: Remove elements that are in mst and dst, but missing from src
  for i := 0 to slMst.Count - 1 do begin
    s_ndx := slSrc.IndexOf(slMst[i]);
    d_ndx := slDst.IndexOf(slMst[i]);
    
    if (s_ndx = -1) and (d_ndx > -1) then begin
      if debugArrays then LogMessage('      > Removing element at '+Path(dst)+' with values: '+slMst[i]);
      RemoveElement(dst, d_ndx);
      slDst.Delete(d_ndx);
    end;
  end;
  
  // Step 3: Copy array elements in src that aren't in mst or dst
  for i := 0 to slSrc.Count - 1 do begin
    d_ndx := slDst.IndexOf(slSrc[i]);
    m_ndx := slMst.IndexOf(slSrc[i]);
    se := ebi(src, i);
    //if debugArrays then LogMessage('Looking to copy '+slSrc[i]);
    if (m_ndx = -1) and (d_ndx = -1) then begin
      if debugArrays then LogMessage('      > Adding element at '+Path(dst)+' with values: '+slSrc[i]);
      ElementAssign(dst, HighInteger, se, false);
      slDst.Add(slSrc[i]);
    end;
  end;
  
  // Step 4: Free lists.
  slMst.Free;
  slSrc.Free;
  slDst.Free;
end;

{
  ListHasMatch
  Check if a list has a matching subrecord
}
function ListHasMatch(var sl: TStringList; input: string): boolean;
var
  i: integer;
  ex: string;
begin
  Result := false;
  for i := 0 to sl.Count - 1 do begin
    ex := sl[i];
    if (Pos('*', ex) > 0) then begin
      SetChar(ex, Pos('*', ex), '');
      if (Pos(ex, input) > 0) then begin
        Result := true;
        exit;
      end;
    end
    else if (ex = input) then begin
      Result := true;
      exit;
    end;
  end;
end;

{
  SkipRecord
  Returns whether or not a record should be skipped
}
function SkipRecord(rec: IInterface; records, recordMode: string): boolean;
var
  s: string;
begin
  s := Signature(rec);
  Result := ((Pos(s, records) > 0) and (recordMode = '0'))
    or ((Pos(s, records) = 0) and (recordMode = '1'))
    or ((Pos(s, global_records) > 0) and (global_recordMode = '0')) 
    or ((Pos(s, global_records) = 0) and (global_recordMode = '1'))
end;

{
  SkipSubrecord
  Check if a subrecord should be skipped
}
function SkipSubrecord(subrecord: IInterface; ini: TMemIniFile): boolean;
var
  subrecords, subrecordMode, subrecordPath: string;
  match, globalMatch: boolean;
begin
  // load subrecord settings
  subrecordMode := ini.ReadString('Setting', 'subrecordMode', '0');
  
  // path string
  subrecordPath := Path(subrecord);
  
  // result boolean
  match := ListHasMatch(slSubrecords, subrecordPath);
  globalMatch := ListHasMatch(slGlobalSubrecords, subrecordPath);
  Result := ((subrecordMode = '0') and (match))
    or ((subrecordMode = '1') and not (match))
    or ((global_subrecordMode = '0') and (globalMatch)) 
    or ((global_subrecordMode = '1') and not (globalMatch));
end;

{
  AddElementsToList
  Adds children elements to a stringlist
}
procedure AddElementsToList(element: IInterface; var sl: TStringList);
var
  i: integer;
  childElement: IInterface;
begin
  for i := 0 to ElementCount(element) - 1 do begin
    childElement := ebi(element, i);
    sl.Add(Name(childElement));
  end;
end;

{
  IsValueElement
  Checks if an element is a value element
}
function IsValueElement(elementType: string): boolean;
begin
  Result := (elementType = 'dtInteger') 
    or (elementType = 'dtFloat') 
    or (elementType = 'dtUnion') 
    or (elementType = 'dtByteArray')
    or (elementType = 'dtString') 
    or (elementType = 'dtLString') 
    or (elementType = 'dtLenString');
end;

{
  rcore
  Recursively Copy Overridden Elements
}
procedure rcore(src, mst, dst, dstrec: IInterface; depth: string; ini: TMemIniFile);
var
  i, j, k, max: integer;
  se, me, de, sse, mse, kse, kme, kde, xse: IInterface;
  mv, sv, ets, dts, cts, cas, ctsrc, subrecords, subrecordMode: string;
  diff: TRecordDiff;
  slDst, slMst: TStringList;
  skip: boolean;
begin
  // initialize stringlists
  slDst := TStringList.Create; // list of destination elements
  slMst := TStringList.Create; // list of master elements
  
  // copy elements from source to destination if missing
  AddElementsToList(dst, slDst);
  AddElementsToList(mst, slMst);
  for i := 0 to ElementCount(src) - 1 do begin
    se := ebi(src, i);
    // if the element isn't in the destination record
    // and wasn't in the master record, copy it to the destination
    // if it isn't in the destination but is in the master it means
    // that it was deleted and shouldn't be copied.
    if (slDst.IndexOf(Name(se)) = -1) 
    and (slMst.IndexOf(Name(se)) = -1) then
      wbCopyElementToRecord(se, dst, false, true);
  end;
  
  // loop through subelements
  i := 0;
  j := 0;
  while i < ElementCount(src) do begin
    // assign source, destination, master elements
    // ensure index out of bounds doesn't occur by not reassigning
    // past the last element
    if i < ElementCount(src) then
      se := ebi(src, i);
    if j < ElementCount(dst) then
      de := ebi(dst, j);
    me := ebn(mst, Name(se));
    
    // DefType and ElementType strings
    ets := ElementTypeString(se);
    dts := DefTypeString(se);
    
    // skip record header, copy record flags
    if Name(se) = 'Record Header' then begin
      wbCopyElementToRecord(ebp(se, 'Record Flags'), dst, false, true);
      Inc(i);
      Inc(j);
      continue;
    end;
    // skip subrecordsToSkip
    skip := SkipSubrecord(se, ini);
    if skip then begin
      if showSkips then LogMessage('    Skipping '+Path(se));
      Inc(i);
      Inc(j);
      continue;
    end;
    
    // debug messages
    if showTraversal then LogMessage('    '+Path(se));
    if showTypeStrings then LogMessage('    ets: '+ets+'  dts: '+dts);
    
    // if destination element doesn't match source element
    if (Name(se) <> Name(de)) then begin
      // if we're not at the end of the destination elements
      // proceed to next destination element
      // else proceed to next source element
      if (j < ElementCount(dst)) then
        Inc(j)
      else
        Inc(i);
      continue;
    end;
    
    // deal with subrecord arrays
    if (ets = 'etSubRecordArray') or (dts = 'dtArray') then begin
      // if sorted, deal with sorted array
      if IsSorted(se) then begin
        if debugArrays then LogMessage('    Sorted array found: '+Path(se));
        try
          MergeSortedArray(me, se, de, dstrec, depth, ini);
        except on x : Exception do
          LogMessage('      !! MergeSortedArray exception: '+x.Message);
        end;
      end
      // else deal with unsorted etSubRecordArray
      else if (ets = 'etSubRecordArray') then begin
        if debugArrays then LogMessage('    Unsorted etSubRecordArray found: '+Path(se));
        try 
          MergeUnsortedArray(me, se, de, dstrec, depth, ini);
        except on x : Exception do
          LogMessage('      !! MergeUnsortedArray exception: '+x.Message);
        end;
      end
      // else deal with unsorted dtArray
      else begin
        if debugArrays then LogMessage('    Unsorted dtArray found: '+Path(se));
        try 
          MergeUnsortedArray(me, se, de, dstrec, depth, ini);
          //rcore(se, me, de, dstrec, depth + ' ', ini);
        except on x : Exception do
          LogMessage('      !! MergeUnsortedArray exception: '+x.Message);
        end;
      end;
    end
    
    // else recurse deeper
    else if (ElementCount(se) > 0) and (dts <> 'dtInteger') then begin
      try
        rcore(se, me, de, dstrec, depth + '    ', ini);
      except on x : Exception do
        LogMessage('      !! rcore exception in element '+Path(se)+': '+x.Message);
      end;
    end
    
    // else copy element if value differs from master
    else if IsValueElement(dts) and (GetEditValue(se) <> GetEditValue(me)) then begin
      if (Assigned(me)) and showChanges then begin
        if (not showTraversal) then LogMessage('    '+Path(se));
        LogMessage('      > Found differing values: '+GetEditValue(se)+' and '+GetEditValue(me));
      end;
      // try to copy element value to destination element from source element
      try 
        SetEditValue(de, GetEditValue(se));
      except on x : Exception do
        LogMessage('      !! Copy element value exception: '+x.Message);
      end;
    end;
    
    // proceed to next subelement
    Inc(i);
    Inc(j);
  end;
  
  slDst.Free;
  slMst.Free;
end;

{
  IsSmashedPatch
  Checks if @f is a smashed patch
}
function IsSmashedPatch(f: IInterface): boolean;
var
  author: string;
begin
  author := geev(ElementByIndex(f, 0), 'CNAM');
  Result := (Pos('Mator Smash', author) = 1); 
end;

{
  SmashRecord
  Smashes @rec into @smashFile.
}
procedure SmashRecord(rec, smashFile: IInterface);
var
  i: integer;
  fn, author: string;
  f, ovr, mr: IInterface;
  ini: TMemIniFile;
begin
  // loop through record's overrides
  for i := 0 to OverrideCount(rec) - 1 do begin
    ovr := OverrideByIndex(rec, i);
    f := GetFile(ovr);
    fn := GetFileName(f);
    
    // skip overrides in bethesda files
    if (Pos(fn, bethesdaFiles) > 0) then
      continue;
    // skip overrides in smashed patches
    if (IsSmashedPatch(f)) then 
      continue;
    // skip ctIdenticalToMaster overrides
    if (ConflictThisForMainRecord(ovr) = ctIdenticalToMaster) then
      continue;
    
    // if master record is not assigned, copy winning override to smashed patch
    if (not Assigned(mr)) then begin
      try
        mr := wbCopyElementToFile(WinningOverride(ovr), smashFile, false, true);
      except on x: Exception do
        LogMessage('      !! Exception copying record '+Name(rec)+' : '+x.Message);
      end;
    end;
    
    // look up setting for this file
    try
      ini := TMemIniFile(lstSettings[slSettings.IndexOf(slOptions[slFiles.IndexOf(fn)])]);
    except on x : Exception do
      LogMessage('Setting lookup exception : '+x.Message);
    end;
    
    // recursively copy overriden elements
    try
      if makeNewLine then LogMessage('');
      LogMessage('Smashing record '+Name(rec)+' from file: '+fn);
      slSubrecords.Text := StringReplace(ini.ReadString('Setting', 'subrecords', ''), '#13', #13, [rfReplaceAll]);
      rcore(ovr, rec, mr, mr, '    ', ini);
    except on x : Exception do
      LogMessage('    !! Exception smashing record '+Name(rec)+' : '+x.Message);
    end;
  end;
end;


{===========================================================}
{ MAIN EXECUTION }


{
  ShowDetails
  Enables the visibilty of the TMemo log
}
procedure ShowDetails;
begin
  frm.Height := 600;
  frm.Position := poScreenCenter;
  memo.Height := frm.Height - 150;
  btnDetails.Visible := false;
  memo.Visible := true;
end;

{
  InitializeSettings
  Loads settings from files
}
procedure InitializeSettings;
var
  i: integer;
  ini: TMemIniFile;
  s: string;
  info: TSearchRec;
begin
  // create lists
  slSettings := TStringList.Create;
  lstSettings := TList.Create;
  
  // load settings
  SetCurrentDir(settingsPath);
  if FindFirst(settingsPath+'*.ini', faAnyFile, info) = 0 then begin
    repeat
      lstSettings.Add(TMemIniFile.Create(settingsPath + info.Name));
    until FindNext(info) <> 0;
  end;
  
  // add setting strings
  for i := 0 to lstSettings.Count - 1 do begin
    s := TMemIniFile(lstSettings[i]).ReadString('Setting', 'Name', '');
    slSettings.Add(s);
  end;
end;

{
  FreeMemory
  Frees memory used by script
}
procedure FreeMemory;
begin
  gear.Free; slOptions.Free; slFiles.Free; slSettings.Free;
  lstSettings.Free;
end;

{
  Initialize
  Load assets, settings, display forms, show progress bar, perform 
  main smashing procedure.
}
function Initialize: integer;
var
  f, r: IInterface;
  i, j, k: integer;
  fn, rn, records, recordMode, logFileName, fdt: string;
  ini: TMemIniFile;
  tStart, tRec: TDateTime;
  diff: double;
  pic: TPicture;
  bmpChecked, bmpUnChecked, bmpPChecked: TBitmap;
begin
  // load tree stringlists
  AssetPath := ScriptsPath + 'smash\assets\';
  recordTree := TStringList.Create;
  recordTree.LoadFromFile(AssetPath + 'RecordTree.txt');
  subrecordTree := TStringList.Create;
  subrecordTree.LoadFromFile(AssetPath + 'SubrecordTree.txt');
  include := TStringList.Create;
  
  // load checkbox images
  checkboxImages := TCustomImageList.Create(nil);
  pic := TPicture.Create;
  
  bmpChecked := TBitmap.Create;
  bmpUnChecked := TBitmap.Create;
  bmpPChecked := TBitmap.Create;
  
  pic.LoadFromFile(AssetPath + 'Check.bmp');
  bmpChecked.SetSize(17, 17);
  bmpChecked.Canvas.Draw(0, 0, pic.Graphic);  
  
  pic.LoadFromFile(AssetPath + 'UnCheck.bmp');
  bmpUnChecked.SetSize(17, 17);
  bmpUnChecked.Canvas.Draw(0, 0, pic.Graphic);  
  
  pic.LoadFromFile(AssetPath + 'PartialCheck.bmp');
  bmpPChecked.SetSize(17, 17);
  bmpPChecked.Canvas.Draw(0, 0, pic.Graphic);  

  checkboxImages.Add(bmpChecked, nil);
  checkboxImages.Add(bmpChecked, nil);
  checkboxImages.Add(bmpUnChecked, nil);
  checkboxImages.Add(bmpPChecked, nil);
  
  // track time
  tStart := Now;
  
  // stringlist creation
  slOptions := TStringList.Create;
  slFiles := TStringList.Create;
  slSubrecords := TStringList.Create;
  slGlobalSubrecords := TStringList.Create;
  makeNewLine := showSkips or showTraversal or debugGetMaster or debugArrays 
    or showChanges or showTypeStrings or showRecTimes;
  
  // load gui elements
  gear := TPicture.Create;
  gear.LoadFromFile(AssetPath + 'gear.png');
  
  // load setting files
  InitializeSettings;
  
  // set up for saving log
  ForceDirectories(ScriptsPath + '\smash\logs');
  fdt := FormatDateTime('mmddyy_hhnnss', Now);
  logFileName := ScriptsPath + '\smash\logs\smash' + fdt + '.txt';
  
  // initial options form
  if OptionsForm then begin
    frm := TForm.Create(nil);
    try 
      frm.Caption := 'Mator Smash!';
      frm.Width := 700;
      frm.Position := poScreenCenter;
      frm.Height := 150;
      
      // make progress label
      lbl := cLabel(frm, frm, 20, 20, 30, 600, 'Initializing...', '');
      
      // make progress bar
      pb := TProgressBar.Create(frm);
      pb.Parent := frm;
      pb.Top := 40;
      pb.Left := 20;
      pb.Width := frm.Width - 55;
      pb.Height := 20;
      pb.Step := 1;
      pb.Min := 0;
      pb.Position := 0;
      
      // make log memo
      memo := cMemo(frm, frm, 70, 20, 0, pb.Width, false, true, ssBoth, '');
      memo.Visible := false;
      
      // make details button
      btnDetails := cButton(frm, frm, pb.Top + pb.Height + 8, pb.Left, 0, 100, 'Show Details');
      btnDetails.OnClick := ShowDetails;
      
      // display form, initial logging messages
      frm.Show;
      application.processmessages;
      LogMessage(dashes);
      LogMessage('Mator Smash '+vs+': Makes a smashed patch.');
      LogMessage(dashes);
     
      // create stringlists
      slRecords := TStringList.Create;
      
      // load global settings
      ini := TMemIniFile(lstSettings[slSettings.IndexOf(global_setting)]);
      global_records := StringReplace(ini.ReadString('Setting', 'records', ''), splitChar, #13#10, [rfReplaceall]);
      global_recordMode := ini.ReadString('Setting', 'recordMode', '0');
      global_subrecords := StringReplace(ini.ReadString('Setting', 'subrecords', ''), splitChar, #13#10, [rfReplaceall]);
      global_subrecordMode := ini.ReadString('Setting', 'subrecordMode', '0');
      slGlobalSubrecords.Text := global_subrecords;
     
      // see if a smashed patch is loaded
      for i := 0 to FileCount - 1 do begin
        f := FileByIndex(i);
        // if smashed patch found, break
        if (IsSmashedPatch(f)) then begin
          userFile := f;
          break;
        end;
      end;
     
      // make userFile if not found
      lbl.Caption := 'Assigning smashed patch.';
      application.processmessages;
      if not Assigned(userFile) then
        userFile := AddNewFile;
      if not Assigned(userFile) then begin
        LogMessage('Smashed patch not assigned, terminating script');
        FreeMemory;
        frm.Free;
        Result := -1;
        exit;
      end;
      
      // set userFile author to Mator Smash
      lbl.Caption := 'Adding masters to smashed patch.';
      application.processmessages;
      seev(ebi(userFile, 0), 'CNAM', 'Mator Smash '+vs);
      // add masters to userFile
      for i := 0 to FileCount - 3 do begin
        f := FileByLoadOrder(i);
        if (IsSmashedPatch(f)) then
          break;
        fn := GetFileName(f);
        AddMasterIfMissing(userFile, fn);
      end;
     
      // loop through all loaded files
      k := 0;
      tRec := Now;
      for i := 0 to FileCount - 1 do begin
        f := FileByIndex(i);
        fn := GetFileName(f);
        
        // skip bethesda files, we're not patching them
        if Pos(fn, bethesdaFiles) > 0 then
          continue;
        // if smashed patch found, break
        if (IsSmashedPatch(f)) then
          break;
        
        // build list of records with multiple overrides
        lbl.Caption := 'Processing '+fn;
        LogMessage('Processing '+fn);
        application.processmessages;
        // load ini settings
        ini := TMemIniFile(lstSettings[slSettings.IndexOf(slOptions[k])]);
        records := StringReplace(ini.ReadString('Setting', 'records', ''), splitChar, #13#10, [rfReplaceAll]);
        recordMode := ini.ReadString('Setting', 'recordMode', '0');
        
        // loop through records
        for j := 0 to RecordCount(f) - 1 do begin
          r := MasterOrSelf(RecordByIndex(f, j));
          if (OverrideCount(r) <= 1) then
            continue;
          // skip records according to ini settings
          if SkipRecord(r, records, recordMode) then 
            continue;
          rn := Name(r);
          if (nbsOverrideCount(r) > 1) then
            if (ConflictThisForMainRecord(WinningOverride(r)) <> ctOverride) then
              if slRecords.IndexOf(rn) = -1 then begin
                slRecords.AddObject(rn, TObject(r));
              end;
        end;
        Inc(k);
      end;
      diff := (Now - tRec) * 86400;
      LogMessage(FormatFloat('0.###', diff) + ' seconds spent processing records.');
     
      // test list of records
      if listOverrides then begin
        LogMessage('');
        for i := 0 to slRecords.Count - 1 do begin
          r := ObjectToElement(slRecords.Objects[i]);
          LogMessage(slRecords[i]+' ('+IntToStr(OverrideCount(r))+' overrides)');
          for j := 0 to OverrideCount(r) - 1 do
            LogMessage('    Override #'+IntToStr(j)+': '+GetFileName(GetFile(OverrideByIndex(r, j))));
        end;
      end;
     
      // smash records that have been overridden multiple times
      lbl.Caption := 'Smashing records (1/'+IntToStr(slRecords.Count)+')';
      application.processmessages;
      pb.Max := slRecords.Count;
      LogMessage('');
      for i := 0 to slRecords.Count - 1 do begin
        tRec := Now;
        if i = maxRecords then break;
        // smash record
        r := ObjectToElement(slRecords.Objects[i]);
        SmashRecord(r, userFile);
        // update label, print debug message to log after smashing record
        lbl.Caption := 'Smashing records ('+IntToStr(i + 2)+'/'+IntToStr(slRecords.Count)+')';
        pb.Position := pb.Position + 1;
        if showRecTimes then begin
          diff := (Now - tRec) * 86400;
          LogMessage('  '+FormatFloat('0.###', diff) + 's');
        end;
        application.processmessages;
      end;
      
      // sort and clean masters
      SortMasters(userFile);
      CleanMasters(userFile);
      
      // finishing messages
      lbl.Caption := 'All done.';
      LogMessage(#13#10+dashes);
      LogMessage('Smashing complete.  '+IntToStr(RecordCount(userfile))+' records smashed.');
      diff := (Now - tStart) * 86400;
      LogMessage('Completed in ' + FormatFloat('0.###', diff) + ' seconds.');
      memo.Lines.SaveToFile(logFileName);
      application.processmessages;
      
      if (memo.Visible) then begin
        frm.Visible := false;
        frm.ShowModal;
      end;
    except on x : Exception do begin
        // smash failed
        LogMessage(#13#10'Smash failed.  Exception: '+x.Message);
        memo.Lines.SaveToFile(logFileName);
        pb.Position := 0;
        lbl.Caption := 'Smash Failed.  Exception: '+x.Message;
        if not memo.Visible then ShowDetails;
        frm.Visible := false;
        frm.ShowModal;
        Application.processmessages;
      end;
    end;
    frm.Free;
  end;

  // free memory
  FreeMemory;

  // call RemoveFilter() to update TES5Edit GUI
  try
    RemoveFilter();
  except on Exception do
    AddMessage(#13#10'You''re not using the latest version of xEdit, so the script couldn''t update the GUI.');
    AddMessage('Right click in the plugin view and click "Remove Filter" to update the GUI manually.');
  end;
end;

end.


================================================
FILE: design/code snippets/better build algorithm.pas
================================================
procedure LoadElementData(var sl: TStringList; container: IwbContainerElementRef);
var
  innerContainer: IwbContainerElementRef;
  element: IwbElement;
begin
  // loop through container's elements
  for i := 0 to Pred(container.ElementCount) do begin
    element := container.Elements[i];
    //if bOverridesOnly and (ConflictThis(element) = ctIdenticalToMaster) then
      //continue;
    index := sl.IndexOf(element.Name);
    // create new element name item if missing
    if index = -1 then
      index := sl.Add(element.Name);
    // traverse children of element, if it has any
    if Supports(element, IwbContainerElementRef, innerContainer) then
      if innerContainer.ElementCount > 0 then begin
        if not Assigned(sl.Objects[index]) then 
          sl.Objects[index] := TStringList.Create;
        LoadElementData(TStringList(sl.Objects[index]), innerContainer); 
      end;
  end;
end;

procedure LoadRecordData(var sl: TStringList; f: IwbFile);
var
  i, index: Integer;
  container: IwbContainerElementRef;
  rec: IwbMainRecord;
begin
  // loop through file's records
  for i := 0 to Pred(f.RecordCount) do begin
    rec := f.Records[i];
    // skip excluded signatures
    if HasSignature(rec.Signature, excludedSignatures) then 
      continue;
    // skip non-override records
    if bOverridesOnly and not IsOverride(rec) then
      continue;
    index := sl.IndexOf(rec.Signature);
    // add new record signature item if missing
    if index = -1 then
      index := sl.AddObject(rec.Signature, TStringList.Create);
    if Supports(rec, IwbContainerElementRef, container) then
      LoadElementData(TStringList(sl.Objects[index]), container);
  end;
end;

procedure StringsToNodes(node: TTreeNode; var sl: TStringList);
var
  child: TTreeNode;
  i: Integer;
begin
  for i := 0 to Pred(sl.Count) do begin
    child := TreeView.Items.AddChild(node, sl[i]);
    child.Data := TElementData.Create(0, false, false, false);
    if Assigned(sl.Objects[i]) then
      StringsToNodes(child, TStringList(sl.Objects[i]));
  end;
end;

procedure TTreeThread.Execute;
var
  i: Integer;
  plugin: TPlugin;
begin
  // ?
  
  // BODY
  sl := TStringList.Create;
  sl.Sorted := true;
  for i := 0 to Pred(pluginsToHandle.Count) do begin
    plugin := TPlugin(pluginsToHandle[i]);
    LoadRecordData(sl, plugin._File);
  end;
  rootNode := TreeView.Items.Add(nil, 'Records');
  StringsToNodes(rootNode, sl);
  
  //?
end;

function GetConflictThis(element: IwbElement): TConflictThis;
var
  mainRecord, master, winning: IwbMainRecord;
begin
  mainRecord := element.ContainingMainRecord;
  if mainRecord.ConflictPriority = cpIgnore then
    Result := ctIgnored
  else if mainRecord.OverrideCount = 0 then
    Result := ctOnlyOne
  else begin  
    master := mainRecord.Master;
    winning := mainRecord.WinningOverride;
    
    masterElement := master.ElementByPath(element.Path);
    winningElement := winning.ElementByPath(element.Path);
  end;
end;

================================================
FILE: design/notes/algorithm problems.txt
================================================
1. Elements with the same name

================================================
FILE: design/notes/handling.txt
================================================
Things to handle: ignoring deletions, treat as single entity, priority, linking

Ignoring deletions:
When applied to an element, ignore deletions in any of its children elements.
-- boolean set to rcore
-- leads us to not call "delete elements if missing"
-- passed to HandleArray

Treat as single entity:
When applied to an element, any change in that its children's values leads us to copy the entire element to replace the destination element.
-- boolean set to rcore
-- rcore made into a function that returns true whenever a change occurs
-- rcore doesn't call CopyElementValue when a value is different, simply returning true instead
-- HandleArray also made into a function that returns true whenever a change occurs
-- Array handlers return true when they detect an element has been added/deleted/changed

Priority:
Overrides load order on a per-element basis.  When priority for an element in a record in a file exceeds the priority of the same element in other files we use that element in destination record.  (remove?)

Linking:


================================================
FILE: design/notes/high level design.txt
================================================
Smash

Q: Do we want profiles?
A: Yes, because a user may have multiple load orders or games they want to use smash with.

Q: Do we want a backend?
A: Yes. We want to serve up smash settings, plugin action recommendations, and program updates.

Q: What will be the main actions of the user within the program?
A: Create a new smashed patch, view/edit smash settings, view a plugin's record makeup, adjust program settings, update the program, download new smash settings, view the help file, submit smash settings, submit plugin action recommendations, build smashed patches, delete smashed patches, rebuild smashed patches, ...

Q: What attributes will a smashed patch have?
A: Plugins, plugin, date built, name, filename, smash setting, status, hashes, fails, files.

Q: What attributes with a smash setting have?
A: A tree of records/subrecord options (process [boolean], treat as single entity [boolean], priority [byte], preserve deletions [boolean]), applicable plugin makeup (record group breakdown), hash, and a name.  All smash settings will be inclusive.

Q: What functionality will smash patch generation make use of?
A: 
- Recursive traversal of records and subrecords
- Record and subrecord skipping based on smash setting
- Single-entity subrecord handling
- Sorted array handling
- Unsorted array handling
- Record/subrecord priority
- Record/subrecord preserve deletions option
- Subrecord/record priority handling
- Subrecord linking (possibly)

Q: What information should we expose on plugins and their record makeup?
A: What record groups are in the plugin.  How many records are in each record group.  The breakdown of new records/override records in the plugin.  The breakdown of new records/overrides in each record group.  A plugin dependency tree.  A breakdown of all record conflicts in the user's load order/between a selected set of plugins.  A breakdown of the elements that conflict in the user's load order/between a selected set of plugins.

Q: What attributes will a plugin recommendation have?
A: Plugin filename, plugin hash, smash setting name, smash setting hash.

Q: How will setting recommendations be computed?
A: Each setting will be compared against the plugin to see how many of the conflicts from the plugin it takes care of, and how well it matches the plugin's record makeup.

================================================
FILE: design/notes/linking explanation.txt
================================================
1. we have a set of plugins
2. each plugin has a smash setting
3. each smash setting has a definition for certain records
4. each record definition has a node for each element
5. we can link a node in a record definition to another node

--

If a element's value changes in a record in a file, and another element is linked to that element, the element that's linked will be copied from the record we're processing to the patch (if it exists).


MASTER:   R2:       R3:       R4:         SMASHED RECORD:
A: 1      A: 2      A: 1      A: 1        A: 1
B: 2      B: 2      B: 2      B: 2        B: 2
C: 3      C: 4      C: 5      C: 3        C: 5

                    LINK A to C
                    Whenever C changes, copy A
                    
                    

================================================
FILE: design/notes/todos 1024.txt
================================================
1. Plugin recommendations "dictionary"
2. Plugin information form (and on main form?)
3. Backend

================================================
FILE: frontend/MatorSmash.dpr
================================================
{*******************************************************************************

     The contents of this file are subject to the Mozilla Public License
     Version 1.1 (the "License"); you may not use this file except in
     compliance with the License. You may obtain a copy of the License at
     http://www.mozilla.org/MPL/

     Software distributed under the License is distributed on an "AS IS"
     basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
     License for the specific language governing rights and limitations
     under the License.

*******************************************************************************}

program MatorSmash;

{$R 'smash.res' 'smash.rc'}

uses
  Forms,
  Dialogs,
  Controls,
  SysUtils,
  // lib\mte
  CRC32 in '..\lib\mte\CRC32.pas',
  mteBase in '..\lib\mte\mteBase.pas',
  mteChangeLogForm in '..\lib\mte\mteChangeLogForm.pas',
  mteHelpers in '..\lib\mte\mteHelpers.pas',
  mteLogger in '..\lib\mte\mteLogger.pas',
  mteLogging in '..\lib\mte\mteLogging.pas',
  mtePluginSelectionForm in '..\lib\mte\mtePluginSelectionForm.pas',
  mteProgressForm in '..\lib\mte\mteProgressForm.pas',
  mteTaskHandler in '..\lib\mte\mteTaskHandler.pas',
  RttiIni in '..\lib\mte\RttiIni.pas',
  RttiJson in '..\lib\mte\RttiJson.pas',
  RttiTranslation in '..\lib\mte\RttiTranslation.pas',
  W7Taskbar in '..\lib\mte\W7Taskbar.pas',
  // lib\xedit
  wbBSA in '..\lib\xedit\wbBSA.pas',
  wbDefinitionsFNV in '..\lib\xedit\wbDefinitionsFNV.pas',
  wbDefinitionsFO3 in '..\lib\xedit\wbDefinitionsFO3.pas',
  wbDefinitionsFO4 in '..\lib\xedit\wbDefinitionsFO4.pas',
  wbDefinitionsTES3 in '..\lib\xedit\wbDefinitionsTES3.pas',
  wbDefinitionsTES4 in '..\lib\xedit\wbDefinitionsTES4.pas',
  wbDefinitionsTES5 in '..\lib\xedit\wbDefinitionsTES5.pas',
  wbHelpers in '..\lib\xedit\wbHelpers.pas',
  wbImplementation in '..\lib\xedit\wbImplementation.pas',
  wbInterface in '..\lib\xedit\wbInterface.pas',
  wbLocalization in '..\lib\xedit\wbLocalization.pas',
  wbSort in '..\lib\xedit\wbSort.pas',
  wbStreams in '..\lib\xedit\wbStreams.pas',
  // Smash
  msConfiguration in 'msConfiguration.pas',
  msCore in 'msCore.pas',
  msLoader in 'msLoader.pas',
  msConflict in 'msConflict.pas',
  msChoicePanel in 'msChoicePanel.pas',
  msSmash in 'msSmash.pas',
  msAlgorithm in 'msAlgorithm.pas',
  msProfileForm in 'msProfileForm.pas' {ProfileForm},
  msProfilePanel in 'msProfilePanel.pas',
  msSmashForm in 'msSmashForm.pas' {SmashForm},
  msThreads in 'msThreads.pas',
  msOptionsForm in 'msOptionsForm.pas' {OptionsForm},
  msSplashForm in 'msSplashForm.pas' {SplashForm},
  msEditForm in 'msEditForm.pas' {EditForm},
  msSettingsManager in 'msSettingsManager.pas' {SettingsManager},
  msPluginSelectionForm in 'msPluginSelectionForm.pas' {MiniPluginSelectionForm},
  msConflictForm in 'msConflictForm.pas' {ConflictForm},
  msTagManager in 'msTagManager.pas' {TagManager},
  msTagHelper in 'msTagHelper.pas' {TagHelper};

{$R *.res}
{$MAXSTACKSIZE 2097152}

const
  IMAGE_FILE_LARGE_ADDRESS_AWARE = $0020;


{$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE}

var
  bProfileProvided, bUseUTF8: boolean;
  sParam, sProfile, sPath: string;
  i: Integer;
  aSettings: TSettings;
begin
  // set important vars
  SysUtils.FormatSettings.DecimalSeparator := '.';
  Application.HintHidePause := 8000;
  //ReportMemoryLeaksOnShutdown := true;
  PathList.Values['ProgramPath'] := ExtractFilePath(ParamStr(0));

  // get current profile if profile switch provided
  for i := 1 to ParamCount do begin
    sParam := ParamStr(i);
    if sParam = '-profile' then
      sProfile := ParamStr(i + 1);
    if sParam = '-utf8' then
      wbStringEncoding := seUTF8;
  end;
  bProfileProvided := sProfile <> '';
  sPath := Format('%sprofiles\%s\settings.ini', [ProgramPath, sProfile]);
  if bProfileProvided and FileExists(sPath) then begin
    aSettings := TSettings.Create;
    TRttiIni.Load(sPath, aSettings);
    CurrentProfile := TProfile.Create(aSettings.profile);
    CurrentProfile.gameMode := aSettings.gameMode;
    CurrentProfile.gamePath := aSettings.gamePath;
    aSettings.Free;
  end;

  // initialize application
  Application.Initialize;
  ForceDirectories(PathList.Values['ProgramPath'] + 'profiles');
  LoadSettings;
  LoadStatistics;

  // have user select game mode
  if not bProfileProvided then begin
    ProfileForm := TProfileForm.Create(nil);
    if not (ProfileForm.ShowModal = mrOk) then
      exit;
    ProfileForm.Free;
  end;

  // run main application
  Application.Title := 'Mator Smash';
  Application.CreateForm(TSmashForm, SmashForm);
  Application.CreateForm(TProfileForm, ProfileForm);
  Application.CreateForm(TOptionsForm, OptionsForm);
  Application.CreateForm(TSplashForm, SplashForm);
  Application.CreateForm(TEditForm, EditForm);
  Application.CreateForm(TSettingsManager, SettingsManager);
  Application.CreateForm(TMiniPluginSelectionForm, MiniPluginSelectionForm);
  Application.CreateForm(TConflictForm, ConflictForm);
  Application.CreateForm(TTagManager, TagManager);
  Application.CreateForm(TTagHelper, TagHelper);
  Application.Run;
end.


================================================
FILE: frontend/MatorSmash.dproj
================================================
	<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
		<PropertyGroup>
			<ProjectGuid>{12317C9C-736E-45A4-8CB7-E43FF92DD93C}</ProjectGuid>
			<MainSource>MatorSmash.dpr</MainSource>
			<Base>True</Base>
			<Config Condition="'$(Config)'==''">Release</Config>
			<AppType>Application</AppType>
			<FrameworkType>VCL</FrameworkType>
			<DCC_DCCCompiler>DCC32</DCC_DCCCompiler>
			<ProjectVersion>13.4</ProjectVersion>
			<Platform Condition="'$(Platform)'==''">Win32</Platform>
			<TargetedPlatforms>1</TargetedPlatforms>
			<Platform>Win32</Platform>
		</PropertyGroup>
		<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
			<Base>true</Base>
		</PropertyGroup>
		<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_2)'!=''">
			<Cfg_2>true</Cfg_2>
			<CfgParent>Base</CfgParent>
			<Base>true</Base>
		</PropertyGroup>
		<PropertyGroup Condition="'$(Config)'=='DebugLite' or '$(Cfg_4)'!=''">
			<Cfg_4>true</Cfg_4>
			<CfgParent>Base</CfgParent>
			<Base>true</Base>
		</PropertyGroup>
		<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_1)'!=''">
			<Cfg_1>true</Cfg_1>
			<CfgParent>Base</CfgParent>
			<Base>true</Base>
		</PropertyGroup>
		<PropertyGroup Condition="'$(Base)'!=''">
			<DCC_UsePackage>vcl;rtl;vclx;vclactnband;xmlrtl;VclSmp;vclimg;svnui;svn;bdertl;TeeUI;TeeDB;Tee;vcldb;dbrtl;vcldbx;vcltouch;dsnap;dsnapcon;vclib;ibxpress;adortl;IndyCore;IndySystem;IndyProtocols;inet;intrawebdb_110_150;Intraweb_110_150;vclie;websnap;webdsnap;inetdb;inetdbbde;inetdbxpress;soaprtl;vclribbon;dbexpress;DbxCommonDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;DataSnapClient;dbxcds;DbxClientDriver;DataSnapServer;AzureCloud;DBXInterBaseDriver;DBXMySQLDriver;DBXFirebirdDriver;DBXSybaseASEDriver;DBXSybaseASADriver;DBXOracleDriver;DBXMSSQLDriver;DBXInformixDriver;DBXDb2Driver</DCC_UsePackage>
			<DCC_UnitSearchPath>..\lib\Imaging\ZLib;..\lib\abbrevia\source;..\lib\Imaging;..\lib\xedit;..\lib\mte;..\lib\superobject;..\lib\xedit\zlib;..\lib\xedit\lz4;$(DCC_UnitSearchPath)</DCC_UnitSearchPath>
			<DCC_SYMBOL_DEPRECATED>false</DCC_SYMBOL_DEPRECATED>
			<DCC_WIDECHAR_REDUCED>false</DCC_WIDECHAR_REDUCED>
			<DCC_SYMBOL_PLATFORM>false</DCC_SYMBOL_PLATFORM>
			<DCC_UNIT_PLATFORM>false</DCC_UNIT_PLATFORM>
			<DCC_COMBINING_SIGNED_UNSIGNED>false</DCC_COMBINING_SIGNED_UNSIGNED>
			<Icon_MainIcon>TES5Edit_Icon.ico</Icon_MainIcon>
			<DCC_IMPLICIT_STRING_CAST>false</DCC_IMPLICIT_STRING_CAST>
			<DCC_COMPARING_SIGNED_UNSIGNED>false</DCC_COMPARING_SIGNED_UNSIGNED>
			<Manifest_File>None</Manifest_File>
			<VerInfo_Locale>3081</VerInfo_Locale>
			<VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
			<DCC_Namespace>Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;FMX;System.Win;$(DCC_Namespace)</DCC_Namespace>
			<DCC_E>false</DCC_E>
			<DCC_ImageBase>00400000</DCC_ImageBase>
			<DCC_F>false</DCC_F>
			<DCC_S>false</DCC_S>
			<DCC_N>false</DCC_N>
			<DCC_K>false</DCC_K>
		</PropertyGroup>
		<PropertyGroup Condition="'$(Cfg_2)'!=''">
			<DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
			<DCC_Define>DEBUG;NX_EXCEPTION_LOG_IN_APP_FOLDER;$(DCC_Define)</DCC_Define>
			<DCC_MapFile>3</DCC_MapFile>
			<ILINK_MapFileType>DetailedSegments</ILINK_MapFileType>
		</PropertyGroup>
		<PropertyGroup Condition="'$(Cfg_4)'!=''">
			<DCC_ExeOutput>.\DebugLite</DCC_ExeOutput>
			<DCC_Define>DEBUG;NX_EXCEPTION_LOG_IN_APP_FOLDER;LiteVersion;$(DCC_Define)</DCC_Define>
			<DCC_MapFile>3</DCC_MapFile>
			<ILINK_MapFileType>DetailedSegments</ILINK_MapFileType>
			<DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
		</PropertyGroup>
		<PropertyGroup Condition="'$(Cfg_1)'!=''">
			<DCC_DebugInformation>false</DCC_DebugInformation>
			<DCC_IOChecking>false</DCC_IOChecking>
			<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
			<DCC_AssertionsAtRuntime>false</DCC_AssertionsAtRuntime>
			<DCC_ImportedDataReferences>false</DCC_ImportedDataReferences>
			<DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
		</PropertyGroup>
		<ItemGroup>
			<DelphiCompile Include="MatorSmash.dpr">
				<MainSource>MainSource</MainSource>
			</DelphiCompile>
			<RcCompile Include="smash.rc">
				<ContainerId>RC</ContainerId>
				<ContainerId>RC</ContainerId>
				<Form>smash.res</Form>
			</RcCompile>
			<DCCReference Include="..\lib\mte\CRC32.pas"/>
			<DCCReference Include="..\lib\mte\mteBase.pas"/>
			<DCCReference Include="..\lib\mte\mteChangeLogForm.pas"/>
			<DCCReference Include="..\lib\mte\mteHelpers.pas"/>
			<DCCReference Include="..\lib\mte\mteLogger.pas"/>
			<DCCReference Include="..\lib\mte\mteLogging.pas"/>
			<DCCReference Include="..\lib\mte\mtePluginSelectionForm.pas"/>
			<DCCReference Include="..\lib\mte\mteProgressForm.pas"/>
			<DCCReference Include="..\lib\mte\mteTaskHandler.pas"/>
			<DCCReference Include="..\lib\mte\RttiIni.pas"/>
			<DCCReference Include="..\lib\mte\RttiJson.pas"/>
			<DCCReference Include="..\lib\mte\RttiTranslation.pas"/>
			<DCCReference Include="..\lib\mte\W7Taskbar.pas"/>
			<DCCReference Include="..\lib\xedit\wbBSA.pas"/>
			<DCCReference Include="..\lib\xedit\wbDefinitionsFNV.pas"/>
			<DCCReference Include="..\lib\xedit\wbDefinitionsFO3.pas"/>
			<DCCReference Include="..\lib\xedit\wbDefinitionsFO4.pas"/>
			<DCCReference Include="..\lib\xedit\wbDefinitionsTES3.pas"/>
			<DCCReference Include="..\lib\xedit\wbDefinitionsTES4.pas"/>
			<DCCReference Include="..\lib\xedit\wbDefinitionsTES5.pas"/>
			<DCCReference Include="..\lib\xedit\wbHelpers.pas"/>
			<DCCReference Include="..\lib\xedit\wbImplementation.pas"/>
			<DCCReference Include="..\lib\xedit\wbInterface.pas"/>
			<DCCReference Include="..\lib\xedit\wbLocalization.pas"/>
			<DCCReference Include="..\lib\xedit\wbSort.pas"/>
			<DCCReference Include="..\lib\xedit\wbStreams.pas"/>
			<DCCReference Include="msConfiguration.pas"/>
			<DCCReference Include="msCore.pas"/>
			<DCCReference Include="msLoader.pas"/>
			<DCCReference Include="msConflict.pas"/>
			<DCCReference Include="msChoicePanel.pas"/>
			<DCCReference Include="msSmash.pas"/>
			<DCCReference Include="msAlgorithm.pas"/>
			<DCCReference Include="msProfileForm.pas">
				<Form>ProfileForm</Form>
			</DCCReference>
			<DCCReference Include="msProfilePanel.pas"/>
			<DCCReference Include="msSmashForm.pas">
				<Form>SmashForm</Form>
			</DCCReference>
			<DCCReference Include="msThreads.pas"/>
			<DCCReference Include="msOptionsForm.pas">
				<Form>OptionsForm</Form>
			</DCCReference>
			<DCCReference Include="msSplashForm.pas">
				<Form>SplashForm</Form>
			</DCCReference>
			<DCCReference Include="msEditForm.pas">
				<Form>EditForm</Form>
			</DCCReference>
			<DCCReference Include="msSettingsManager.pas">
				<Form>SettingsManager</Form>
			</DCCReference>
			<DCCReference Include="msPluginSelectionForm.pas">
				<Form>MiniPluginSelectionForm</Form>
			</DCCReference>
			<DCCReference Include="msConflictForm.pas">
				<Form>ConflictForm</Form>
			</DCCReference>
			<DCCReference Include="msTagManager.pas">
				<Form>TagManager</Form>
			</DCCReference>
			<DCCReference Include="msTagHelper.pas">
				<Form>TagHelper</Form>
			</DCCReference>
			<None Include="ModelSupport_MatorSmash\default.txvpck"/>
			<BuildConfiguration Include="Debug">
				<Key>Cfg_2</Key>
				<CfgParent>Base</CfgParent>
			</BuildConfiguration>
			<BuildConfiguration Include="DebugLite">
				<Key>Cfg_4</Key>
				<CfgParent>Base</CfgParent>
			</BuildConfiguration>
			<BuildConfiguration Include="Base">
				<Key>Base</Key>
			</BuildConfiguration>
			<BuildConfiguration Include="Release">
				<Key>Cfg_1</Key>
				<CfgParent>Base</CfgParent>
			</BuildConfiguration>
		</ItemGroup>
		<Import Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')" Project="$(BDS)\Bin\CodeGear.Delphi.Targets"/>
		<Import Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')" Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj"/>
		<ProjectExtensions>
			<Borland.Personality>Delphi.Personality.12</Borland.Personality>
			<Borland.ProjectType>VCLApplication</Borland.ProjectType>
			<BorlandProject>
				<Delphi.Personality>
					<Source>
						<Source Name="MainSource">MatorSmash.dpr</Source>
					</Source>
					<VersionInfo>
						<VersionInfo Name="IncludeVerInfo">True</VersionInfo>
						<VersionInfo Name="AutoIncBuild">False</VersionInfo>
						<VersionInfo Name="MajorVer">1</VersionInfo>
						<VersionInfo Name="MinorVer">0</VersionInfo>
						<VersionInfo Name="Release">1</VersionInfo>
						<VersionInfo Name="Build">0</VersionInfo>
						<VersionInfo Name="Debug">True</VersionInfo>
						<VersionInfo Name="PreRelease">True</VersionInfo>
						<VersionInfo Name="Special">False</VersionInfo>
						<VersionInfo Name="Private">False</VersionInfo>
						<VersionInfo Name="DLL">False</VersionInfo>
						<VersionInfo Name="Locale">1033</VersionInfo>
						<VersionInfo Name="CodePage">1252</VersionInfo>
					</VersionInfo>
					<VersionInfoKeys>
						<VersionInfoKeys Name="CompanyName"/>
						<VersionInfoKeys Name="FileDescription"/>
						<VersionInfoKeys Name="FileVersion">1.0.1.0</VersionInfoKeys>
						<VersionInfoKeys Name="InternalName"/>
						<VersionInfoKeys Name="LegalCopyright"/>
						<VersionInfoKeys Name="LegalTrademarks"/>
						<VersionInfoKeys Name="OriginalFilename"/>
						<VersionInfoKeys Name="ProductName">Mator Smash</VersionInfoKeys>
						<VersionInfoKeys Name="ProductVersion">1.0</VersionInfoKeys>
						<VersionInfoKeys Name="Comments">created by matortheeternal</VersionInfoKeys>
					</VersionInfoKeys>
					<Excluded_Packages>
						<Excluded_Packages Name="$(BDSBIN)\bcboffice2k150.bpl">Embarcadero C++Builder Office 2000 Servers Package</Excluded_Packages>
						<Excluded_Packages Name="$(BDSBIN)\bcbofficexp150.bpl">Embarcadero C++Builder Office XP Servers Package</Excluded_Packages>
						<Excluded_Packages Name="$(BDSBIN)\dcloffice2k150.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
						<Excluded_Packages Name="$(BDSBIN)\dclofficexp150.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
					</Excluded_Packages>
					<Parameters_Win32/>
				</Delphi.Personality>
				<Platforms>
					<Platform value="Win64">False</Platform>
					<Platform value="Win32">True</Platform>
				</Platforms>
				<ModelSupport>True</ModelSupport>
			</BorlandProject>
			<ProjectFileVersion>12</ProjectFileVersion>
		</ProjectExtensions>
	</Project>


================================================
FILE: frontend/MatorSmash.mes
================================================
[GeneralSettings]
MesVersion=4
HandleExceptions=0
LinkInCode=1
AppendMapFileToBinary=1
NoOwnMadExceptSettings=0
CheckFileCrc=1
CheckForFrozenMainThread=0
FreezeTimeout=60000
ReportLeaks=0
WindowsLogo=0
CrashOnBuffer=0
CrashOnUnderrun=0
AutomaticallySaveBugReport=1
AutoSaveBugReportIfNotSent=0
AutomaticallyMailBugReport=0
AutoMailProgressBox=0
CopyBugReportToClipboard=0
SuspendAllRunningThreads=0
ShowPleaseWaitBox=0
PleaseWaitIcon=plwait1
AutomaticallyContinueApplication=1
AutomaticallyRestartApplication=0
AutomaticallyCloseApplication=0
SendInBackground=0
SendHelper=196608
Send32Icon=send321
UploadViaHttp=0
HttpServer=
HttpSsl=0
HttpPort=0
HttpAccount=
HttpPassword=
UploadToFogBugz=0
UploadToBugZilla=0
UploadToMantis=0
BugTrackerAccount=
BugTrackerPassword=
BugTrackerProject=
BugTrackerArea=
BugTrackerAssignTo=
MailAsSmtpServer=0
MailAsSmtpClient=0
SmtpServer=
SmtpSsl=0
SmtpTls=0
SmtpPort=0
SmtpAccount=
SmtpPassword=
MailViaMapi=0
MailViaMailto=0
MailAddress=
BugReportFile=bugreport.txt
AttachBugReport=0
AttachBugReportFile=1
DeleteBugReportFile=1
BugReportSendAs=bugreport.txt
BugReportZip=
ScreenShotDepth=0
ScreenShotAppOnly=0
ScreenShotSendAs=screenshot.png
ScreenShotZip=
AdditionalAttachments=
AppendBugReports=1
BugReportFileSize=100000
DontSaveDuplicateExceptions=1
DontSaveDuplicateFreezings=1
DuplicateExceptionDefinition=1
DuplicateFreezeDefinition=2
ShowExceptionBox=1
OkBtnText=&OK
DetailsBtnText=&Details
PleaseWaitTitle=Information
PleaseWaitText=Please wait a moment...
BugTrackerTitle=%25appname%25, %25exceptMsg%25
BugTrackerDescr=error details: %0d%0a%25errorDetails%25
MailSubject=bug report
MailBody=please find the bug report attached
SendBoxTitle=Sending bug report...
PrepareAttachMsg=Preparing attachments...
MxLookupMsg=Searching for mail server...
ConnectMsg=Connecting to server...
SendMailMsg=Sending mail...
FieldsMsg=Setting fields...
SendAttachMsg=Sending attachments...
SendFinalizeMsg=Finalizing...
MailFailureMsg=Sorry, sending the bug report didn't work.
VersionVariable=
[ExceptionBox]
ShowButtonMailBugReport=0
ShowButtonSaveBugReport=0
ShowButtonPrintBugReport=0
ShowButtonShowBugReport=1
ShowButtonContinueApplication=1
ShowButtonRestartApplication=1
ShowButtonCloseApplication=1
IconButtonSendBugReport=send1
IconButtonSaveBugReport=save1
IconButtonPrintBugReport=print1
IconButtonShowBugReport=show1
IconButtonContinueApplication=continue1
IconButtonCantContinueApplication=cantContinue1
IconButtonRestartApplication=restart1
IconButtonCloseApplication=close1
FocusedButton=4
SendAssistant=SendAssistant
SaveAssistant=SaveAssistant
PrintAssistant=PrintAssistant
AutomaticallyShowBugReport=0
NoOwnerDrawButtons=0
BigExceptionIcon=big1
TitleBar=%25appname%25
ExceptionMessage=An error occurred in the application.
FrozenMessage=The application seems to be frozen.
BitFaultMsg=The file "%25modname%25" seems to be corrupt!
MailBugReportText=send bug report
SaveBugReportText=save bug report
PrintBugReportText=print bug report
ShowBugReportText=show bug report
ContinueApplicationText=continue application
RestartApplicationText=restart application
CloseApplicationText=close application
[BugReport]
ListThreads=1
ListModules=1
ListHardware=1
ShowCpuRegisters=1
ShowStackDump=1
Disassembly=1
HideUglyItems=0
ShowRelativeAddrs=1
ShowRelativeLines=1
FormatDisassembly=0
LimitDisassembly=5
EnabledPlugins=modules|processes|hardware
[Filters]
Filter1ExceptionClasses=
Filter1DontCreateBugReport=0
Filter1DontCreateScreenshot=0
Filter1DontSuspendThreads=0
Filter1DontCallHandlers=0
Filter1ShowBox=3
Filter1Assis=
Filter2ExceptionClasses=
Filter2DontCreateBugReport=0
Filter2DontCreateScreenshot=0
Filter2DontSuspendThreads=0
Filter2DontCallHandlers=0
Filter2ShowBox=0
Filter2Assis=
GeneralDontCreateBugReport=0
GeneralDontCreateScreenshot=0
GeneralDontSuspendThreads=0
GeneralDontCallHandlers=0
GeneralShowBox=0
GeneralAssis=
[Assistants]
Assistant1=SendAssistant|Send Assistant|ContactForm|DetailsForm|ScrShotForm
Assistant2=SaveAssistant|Save Assistant|ContactForm|DetailsForm
Assistant3=PrintAssistant|Print Assistant|ContactForm|DetailsForm
Forms1=TPF0%0eTMEContactForm%0bContactForm%07Message%0c%13%00%00%00Contact Information%08MinWidth%04%00%00%00%00%08OnAction%0c%1b%00%00%00madExcept.HandleContactForm%05Timer%04%00%00%00%00%00%09INVButton%0bContinueBtn%07Caption%0c%08%00%00%00Continue%07Enabled%09%0bNoOwnerDraw%08%07Visible%09%00%00%09INVButton%07SkipBtn%07Caption%0c%04%00%00%00Skip%07Enabled%08%0bNoOwnerDraw%08%07Visible%09%00%00%09INVButton%09CancelBtn%07Caption%0c%06%00%00%00Cancel%07Enabled%09%0bNoOwnerDraw%08%07Visible%09%00%00%08INVLabel%06Label1%07Caption%0c%0a%00%00%00your name:%07Enabled%09%07Spacing%04%00%00%00%00%00%00%07INVEdit%08NameEdit%07Colored%09%07Enabled%09%05Lines%04%01%00%00%00%08Optional%09%0aOutputName%0c%0c%00%00%00contact name%0aOutputType%07%09nvoHeader%07Spacing%04%00%00%00%00%04Text%0c%00%00%00%00%05Valid%09%00%00%08INVLabel%06Label2%07Caption%0c%0b%00%00%00your email:%07Enabled%09%07Spacing%04%00%00%00%00%00%00%07INVEdit%09EmailEdit%07Colored%09%07Enabled%09%05Lines%04%01%00%00%00%08Optional%08%0aOutputName%0c%0d%00%00%00contact email%0aOutputType%07%09nvoHeader%07Spacing%04%00%00%00%00%04Text%0c%00%00%00%00%05Valid%09%00%00%0bINVCheckBox%08MemCheck%07Caption%0c%0b%00%00%00remember me%07Checked%08%07Enabled%09%0aOutputName%0c%00%00%00%00%07Spacing%04%00%00%00%00%00%00%00
Forms2=TPF0%0eTMEDetailsForm%0bDetailsForm%07Message%0c%0d%00%00%00Error Details%08MinWidth%04%00%00%00%00%08OnAction%0c%00%00%00%00%05Timer%04%00%00%00%00%00%09INVButton%0bContinueBtn%07Caption%0c%08%00%00%00Continue%07Enabled%09%0bNoOwnerDraw%08%07Visible%09%00%00%09INVButton%07SkipBtn%07Caption%0c%04%00%00%00Skip%07Enabled%09%0bNoOwnerDraw%08%07Visible%09%00%00%09INVButton%09CancelBtn%07Caption%0c%06%00%00%00Cancel%07Enabled%09%0bNoOwnerDraw%08%07Visible%09%00%00%08INVLabel%06Label1%07Caption%0c,%00%00%00what were you doing when the error occurred?%07Enabled%09%07Spacing%04%00%00%00%00%00%00%07INVEdit%0bDetailsMemo%07Colored%09%07Enabled%09%05Lines%04%09%00%00%00%08Optional%08%0aOutputName%0c%0d%00%00%00error details%0aOutputType%07%0dnvoOwnSection%07Spacing%04%00%00%00%00%04Text%0c%00%00%00%00%05Valid%09%00%00%00
Forms3=TPF0%0eTMEScrShotForm%0bScrShotForm%0dActiveControl%07%0bContinueBtn%07Message%0c%18%00%00%00Screenshot Configuration%08MinWidth%04%00%00%00%00%08OnAction%0c%1e%00%00%00madExcept.HandleScreenshotForm%05Timer%04%fa%00%00%00%00%09INVButton%0bContinueBtn%07Caption%0c%08%00%00%00Continue%07Enabled%09%0bNoOwnerDraw%08%07Visible%09%00%00%09INVButton%07SkipBtn%07Caption%0c%04%00%00%00Skip%07Enabled%08%0bNoOwnerDraw%08%07Visible%09%00%00%09INVButton%09CancelBtn%07Caption%0c%06%00%00%00Cancel%07Enabled%09%0bNoOwnerDraw%08%07Visible%09%00%00%0bINVCheckBox%0bAttachCheck%07Caption%0c%25%00%00%00attach a screenshot to the bug report%07Checked%09%07Enabled%09%0aOutputName%0c%00%00%00%00%07Spacing%04%00%00%00%00%00%00%08INVImage%0aScrShotImg%06Border%09%09Clickable%09%07Enabled%09%04File%0c%00%00%00%00%06Height%04%00%00%00%00%07Spacing%04%00%00%00%00%05Width%04%00%00%00%00%00%00%08INVLabel%06Label1%07Caption%0c%15%00%00%00(click to edit image)%07Enabled%09%07Spacing%04%00%00%00%00%00%00%00


================================================
FILE: frontend/ModelSupport_MatorSmash/MatorSmash/default.txvpck
================================================
<?xml version="1.0" encoding="utf-8"?>
<nodeSet version="1.0">
  <view uin="b4zfh5af0zf_v">
    <property name="$defaultDiagram" value="true" />
    <property name="$metaclass" value="Package Diagram" />
    <property name="$name" value="default" />
  </view>
</nodeSet>

================================================
FILE: frontend/ModelSupport_MatorSmash/default.txvpck
================================================
<?xml version="1.0" encoding="utf-8"?>
<nodeSet version="1.0">
  <view uin="ea9vm1284dq_v">
    <property name="$defaultDiagram" value="true" />
    <property name="$metaclass" value="Package Diagram" />
    <property name="$name" value="default" />
  </view>
</nodeSet>

================================================
FILE: frontend/ModelSupport_MatorSmash/msEditForm/default.txvpck
================================================
<?xml version="1.0" encoding="utf-8"?>
<nodeSet version="1.0">
  <view uin="njkyjunm3h_v">
    <property name="$defaultDiagram" value="true" />
    <property name="$metaclass" value="Package Diagram" />
    <property name="$name" value="default" />
  </view>
</nodeSet>

================================================
FILE: frontend/ModelSupport_MatorSmash/msFrontend/default.txvpck
================================================
<?xml version="1.0" encoding="utf-8"?>
<nodeSet version="1.0">
  <view uin="n0j337jkpef_v">
    <property name="$defaultDiagram" value="true" />
    <property name="$metaclass" value="Package Diagram" />
    <property name="$name" value="default" />
  </view>
</nodeSet>

================================================
FILE: frontend/ModelSupport_MatorSmash/msOptionsForm/default.txvpck
================================================
<?xml version="1.0" encoding="utf-8"?>
<nodeSet version="1.0">
  <view uin="z6ar60bu6om_v">
    <property name="$defaultDiagram" value="true" />
    <property name="$metaclass" value="Package Diagram" />
    <property name="$name" value="default" />
  </view>
</nodeSet>

================================================
FILE: frontend/ModelSupport_MatorSmash/msProfileForm/default.txvpck
================================================
<?xml version="1.0" encoding="utf-8"?>
<nodeSet version="1.0">
  <view uin="y0bo0tytf3p_v">
    <property name="$defaultDiagram" value="true" />
    <property name="$metaclass" value="Package Diagram" />
    <property name="$name" value="default" />
  </view>
</nodeSet>

================================================
FILE: frontend/ModelSupport_MatorSmash/msProfilePanel/default.txvpck
================================================
<?xml version="1.0" encoding="utf-8"?>
<nodeSet version="1.0">
  <view uin="ac7klwk840k_v">
    <property name="$defaultDiagram" value="true" />
    <property name="$metaclass" value="Package Diagram" />
    <property name="$name" value="default" />
  </view>
</nodeSet>

================================================
FILE: frontend/ModelSupport_MatorSmash/msSmashForm/default.txvpck
================================================
<?xml version="1.0" encoding="utf-8"?>
<nodeSet version="1.0">
  <view uin="d40chv15btm_v">
    <property name="$defaultDiagram" value="true" />
    <property name="$metaclass" value="Package Diagram" />
    <property name="$name" value="default" />
  </view>
</nodeSet>

================================================
FILE: frontend/ModelSupport_MatorSmash/msSplashForm/default.txvpck
================================================
<?xml version="1.0" encoding="utf-8"?>
<nodeSet version="1.0">
  <view uin="xigiykmxj3j_v">
    <property name="$defaultDiagram" value="true" />
    <property name="$metaclass" value="Package Diagram" />
    <property name="$name" value="default" />
  </view>
</nodeSet>

================================================
FILE: frontend/ModelSupport_MatorSmash/msThreads/default.txvpck
================================================
<?xml version="1.0" encoding="utf-8"?>
<nodeSet version="1.0">
  <view uin="y6gq3u7hleh_v">
    <property name="$defaultDiagram" value="true" />
    <property name="$metaclass" value="Package Diagram" />
    <property name="$name" value="default" />
  </view>
</nodeSet>

================================================
FILE: frontend/lang/english.lang
================================================
{ TSmashForm }
{ ## QuickBar ## }
msMain_QuickButton_Hint=Quick patch|Apply Smash.All to loaded plugins and #13#10generate a smashed patch.#13#10
msMain_NewButton_Hint=Create new smashed patch|Make a new empty smashed patch.
msMain_BuildButton_Hint=Build patches|
msMain_ManageButton_Hint=Manage smash settings|Click here to manage smash settings.
msMain_OptionsButton_Hint=Options|Change the options that control how the #13#10program runs.#13#10
{ #### DYNAMIC #### }
msMain_NoPatches=There aren't any patches to build or rebuild.
msMain_BuildPatches_Loader=You can't build patches until the background #13#10loader is done.#13#10
msMain_BuildAllPatches=Builds all patches that are ready to be built or #13#10rebuilt.#13#10
{ ## Main Panel ## }
{ ## Details Panel ## }
msMain_DetailsLabel_Caption=Details
msMain_DetailsCopyToClipboardItem_Caption=Copy to clipboard
{ ## Plugins Tab ## }
msMain_PluginsTabSheet_Caption=Plugins
msMain_PluginsListView_Column0=Index
msMain_PluginsListView_Column1=Filename
msMain_PluginsListView_Column2=Setting
msMain_PluginsListView_Column3=Patch
{ #### DYNAMIC #### }
msMain_PluginDetails=Plugin Details
msMain_Filename=Filename
msMain_Hash=Hash
msMain_FileSize=File Size
msMain_DateModified=Date Modified
msMain_NumRecords=Number of records
msMain_NumOverrides=Number of overrides
msMain_Author=Author
msMain_Description=Description
msMain_Masters=Masters
msMain_ClearTags=Are you sure you want to clear tags from these plugins?
{ ## Plugins Popup Menu ## }
msMain_NewPatchItem_Caption=<New Patch>
msMain_OpenPluginLocationItem_Caption=Open plugin location
msMain_AddToPatchItem_Caption=Add to patch
msMain_ManageTagsItem_Caption=Manage Tags
msMain_SmashSettingItem_Caption=Smash setting
{ ## Patches Tab ## }
msMain_PatchesTabSheet_Caption=Patches
msMain_PatchesListView_Column0=Index
msMain_PatchesListView_Column1=Name
msMain_PatchesListView_Column2=Filename
msMain_PatchesListView_Column3=Size
msMain_PatchesListView_Column4=Date built
{ #### DYNAMIC #### }
msMain_PatchDetails=Patch Details
msMain_Status=Status
msMain_PatchName=Patch name
msMain_PluginCount=Plugin count
msMain_DateBuilt=Date built
msMain_Plugins=Plugins
msMain_Fails=Fails
msMain_TooManyFails=Too many fails to display.
msMain_DeletePatches=Are you sure you want to delete these patches?
{ ## Patches Popup Menu ## }
msMain_ToggleRebuildItem_Caption=Toggle rebuild status
msMain_OpenInExplorerItem_Caption=Open in explorer
{ ## Plugins Submenu ## }
msMain_MoveItem_Caption=Move
msMain_UpItem_Caption=Up
msMain_DownItem_Caption=Down
msMain_ToTopItem_Caption=To top
msMain_ToBottomItem_Caption=To bottom
{ #### DYNAMIC #### }
msMain_BuildPatch=Build patch
msMain_RebuildPatch=Rebuild patch
msMain_BuildPatches=Build patches
msMain_RebuildPatches=Rebuilds patches
{ ## Log Tab ## }
msMain_LogTabSheet_Caption=Log
{ #### DYNAMIC #### }
msMain_AppDetails=Application Details
msMain_Application=Application
msMain_Author=Author
msMain_Version=Version
msMain_DateBuilt=Date built
msMain_GameMode=Game mode
msMain_Language=Language
msMain_TimesRun=Times run
msMain_PatchesBuilt=Patches built
msMain_PluginsSmashed=Plugins smashed
msMain_SettingsSubmitted=Smash settings submitted
msMain_RecsSubmitted=Recommendations submitted
msMain_Website=Website
msMain_ApiCredits=API Credits
msMain_xEditVersion=xEdit Version
msMain_xEditCredits=xEdit Credits
msMain_Testers=Testers
msMain_Translators=Translators
msMain_LoadException=Exception Loading Plugins
msMain_PluginsNotLoaded=Due to an exception, not all of your plugins #13#10have been loaded.  You can still use the program. #13#10See the log tab for more info.#13#10
msMain_Enable=Enable
msMain_Disable=Disable
msMain_AutoScroll=Autoscroll
{ ## Log Popup Menu ## }
msMain_FilterGroupItem_Caption=Filter group
msMain_FilterLabelItem_Caption=Filter label
msMain_CopyToClipboardItem_Caption=Copy to clipboard
msMain_SaveAndClearItem_Caption=Save and clear
msMain_ToggleAutoScrollItem_Caption=Disable auto scroll
 
{ TOptionsForm }
mpOpt_btnCancel_Caption=Cancel
mpOpt_btnOK_Caption=OK
{ ## General Tab ## }
mpOpt_GeneralTabSheet_Caption=General
mpOpt_gbLanguage_Caption=Language
mpOpt_lblLanguage_Caption=Current languge
mpOpt_gbStyle_Caption=Style
mpOpt_kbSimpleDictionary_Caption=Simple dictionary view
mpOpt_kbSimplePlugins_Caption=Simple plugins list
{ ## Patching Tab ## }
mpOpt_PatchingTabSheet_Caption=Patching
mpOpt_lblDestinationDirectory_Caption=Patch destination directory
mpOpt_gbDebug_Caption=Debug
mpOpt_gbOther_Caption=Other Options
{ ## Advanced Tab ## }
mpOpt_AdvancedTabSheet_Caption=Advanced
mpOpt_lblCurrentProfile_Caption=Current profile
mpOpt_gbLogging_Caption=Logging
mpOpt_lblClientColor_Caption=Client
mpOpt_lblGeneralColor_Caption=General
mpOpt_lblLoadColor_Caption=Load
mpOpt_lblPluginColor_Caption=Plugin
mpOpt_lblErrorColor_Caption=Errors
mpOpt_lblTemplate_Caption=Template
mpOpt_lblSample_Caption=Sample
 
{ TSettingsManager }
{ ## Settings ## }
msSet_gbFiltering_Caption=Filtering options
msSet_lvSettings_Column0=Name
msSet_lvSettings_Column1=Records
msSet_btnSave_Caption=Save
msSet_btnDiscard_Caption=Discard
{ ## Settings Popup Menu ## }
msSet_NewSettingItem_Caption=New setting
msSet_CloneSettingItem_Caption=Clone setting
msSet_CombineSettingsItem_Caption=Combine settings
msSet_EditSettingItem_Caption=Edit setting
msSet_DeleteSettingItem_Caption=Delete setting
{ ## Details ## }
msSet_lblName_Caption=Name
msSet_lblColor_Caption=Color
msSet_lblDescription_Caption=Description
msSet_lblTree_Caption=Tree
{ ## Tree Popup Menu ## }
msSet_ToggleNodesItem_Caption=Toggle nodes
msSet_IgnoreDeletionsItem_Caption=Toggle ignore deletions
msSet_SingleEntityItem_Caption=Toggle treat as single entity
msSet_PruneNodesItem_Caption=Prune nodes
msSet_PreserveDeletionsItem_Caption=Toggle preserve deletions

{ TTagManager }
msTagM_Caption=Manage Tags - %s
{ ## General ## }
msTagM_lblDescription_Caption=Description
msTagM_btnAdd_Caption=Add Tags
msTagM_btnRemove_Caption=Remove Tags
msTagM_btnClear_Caption=Clear Tags
msTagM_btnReset_Caption=Reset Tags
msTagM_btnApply_Caption=Apply
msTagM_btnCancel_Caption=Cancel
msTagM_kbCombine_Caption=Apply combined setting

{ TTagHelper }
msTagH_btnCancel_Caption=Cancel
msTagH_btnOK_Caption=OK
{ #### DYNAMIC #### }
msTagH_AddTags=Add Tags
msTagH_RemoveTags=Remove Tags
msTagH_PromptAdd=Check the tags you want to add
msTagH_PromptRemove=Check the tags you want to remove

{ TProgressForm }
{ #### DYNAMIC #### }
msProg_Closing=Closing
msProg_Smashing=Smashing Patches
msProg_DoneBuilding=Done smashing patches
msProg_BuildingTree=Building tree

================================================
FILE: frontend/msAlgorithm.pas
================================================
unit msAlgorithm;

interface

uses
  SysUtils, Classes,
  // superobject
  superobject,
  // mte units
  mteHelpers, mteTracker, mteBase,
  // ms units
  msCore, msConfiguration,
  // xEdit components
  wbInterface, wbImplementation;

  procedure CopyLinkedElement(srcCont, dstCont: IwbContainerElementRef;
    eLink: string; obj: ISuperObject; dstRec: IwbMainRecord);
  function rcore(src, mst, dst: IwbElement; dstrec: IwbMainRecord;
    obj: ISuperObject; bSingle, bDeletions, bOverride: boolean): boolean;

implementation

var
  firstLink: string;
  bLinkProcessed: boolean;

{ 
  ElementByKey: 
  Gets an element from a container, @e, matching a specified @key.
  If @bUseSortKey is true uses SortKey, else uses GetAllValues.
}
function ElementByKey(e: IwbElement; key: string; bUseSortKey: boolean): IwbElement;
var
  i: Integer;
  c: IwbContainerElementRef;
  element: IwbElement;
  eKey: string;
begin
  if not Supports(e, IwbContainerElementRef, c) then 
    exit;
  
  // loop through children elements
  for i := 0 to Pred(c.ElementCount) do begin
    element := c.Elements[i];
    // get sort key if bUseSortKey, else get values key
    if bUseSortKey then
      eKey := element.SortKey[false]
    else
      eKey := GetAllValues(element);
    // if keys match result is current element
    if eKey = key then begin
      Result := element;
      break;
    end;
  end;
end;

{
  HandleElementLife:
  Called by rcore.  Handles the creation/deletion of elements in the
  destination patch record @dstRec.
}
function HandleElementLife(srcCont, dstCont, mstCont: IwbContainerElementRef;
  dstRec: IwbMainRecord; obj: ISuperObject; bSingle, bDeletions, bOverride: boolean): boolean;
var
  i: Integer;
  element: IwbElement;
  eObj: ISuperObject;
  process, bInDestination, bInMaster: boolean;
  eLink: String;
begin
  Result := false;

  // handle element creation
  for i := 0 to Pred(srcCont.ElementCount) do begin
    element := srcCont.Elements[i];

    // if the element isn't in the destination record
    // and wasn't in the master record, copy it to the destination
    // if it isn't in the destination but is in the master it means
    // that it was deleted and shouldn't be copied.
    bInDestination := Assigned(dstCont.ElementByName[element.Name]);
    bInMaster := Assigned(mstCont.ElementByName[element.Name]);
    if (not bInDestination) and (bOverride or not bInMaster) then begin
      Result := true;
      if bSingle then 
        exit;

      // skip according to setting
      eObj := GetElementObj(obj, element.Name);
      process := Assigned(eObj) and (eObj.I['p'] = 1);
      if not process then begin
        if settings.debugSkips then
          Tracker.Write('      Skipping element creation at '+element.Path);
        continue;
      end;

      // copy element
      try
        if settings.debugChanges then
          Tracker.Write('      Created element at '+element.Path);
        wbCopyElementToRecord(element, dstRec, false, true);

        // if another element is linked to the element, copy it
        eLink := eObj.S['lf'];
        if (eLink <> '') then begin
          firstLink := eLink;
          bLinkProcessed := false;
          CopyLinkedElement(srcCont, dstCont, eLink, obj, dstRec);
        end;
      except
        on x: Exception do
          Tracker.Write('        HandleElementLife: Failed to copy '+element.Path+', '+x.Message);
      end;
    end;
  end;

  // handle element deletion
  if bDeletions then begin
    for i := Pred(dstCont.ElementCount) downto 0 do begin
      element := dstCont.Elements[i];
      if Assigned(mstCont.ElementByName[element.Name]) and 
      not Assigned(srcCont.ElementByName[element.Name]) then begin
        Result := true;
        if bSingle then
          exit;

        // skip according to setting
        eObj := GetElementObj(obj, element.Name);
        process := Assigned(eObj) and (eObj.I['p'] = 1);
        if not process then begin
          if settings.debugSkips then
            Tracker.Write('      Skipping element deletion at '+element.Path);
          continue;
        end;

        // remove element
        if settings.debugChanges then
          Tracker.Write('      Deleted element at '+element.Path);
        dstCont.RemoveElement(element);

        // if another element is linked to the element, copy it
        eLink := eObj.S['lf'];
        if (eLink <> '') then begin
          firstLink := eLink;
          bLinkProcessed := false;
          CopyLinkedElement(srcCont, dstCont, eLink, obj, dstRec);
        end;
      end;
    end;
  end;
end;

// GetMasterElement: Gets the first instance of an element (the master)
function GetMasterElement(src, se: IwbElement; dstRec: IwbMainRecord): IwbElement;
const
  debugGetMaster = false;
var
  i: integer;
  path, key: string;
  mstRec, ovr: IwbMainRecord;
  mst: IwbElement;
  bSorted: boolean;
begin
  Result := nil;
  mstRec := dstRec.MasterOrSelf;
  path := IndexedPath(src);
  bSorted := IsSorted(src);
  
  // if sorted, use SortKey, else use GetAllValues
  if bSorted then 
    key := se.SortKey[false]
  else
    key := GetAllValues(se);
    
  // debug message
  if debugGetMaster then 
    Tracker.Write('      Called GetMasterElement at path '+path+' looking for key '+key);
    
  // loop from override 0 to the second to last override
  // last override is in our patch, we don't want to process that one
  for i := 0 to mstRec.OverrideCount - 2 do begin
    ovr := mstRec.Overrides[i];
    mst := ElementByIndexedPath(mstRec, path);
    Result := ElementByKey(mst, key, bSorted);
    
    // break if we found a subrecord matching the sortkey
    if Result <> nil then
      break;
  end;
end;

{
  BuildKeyList:
  Creates a list of element keys for elements in @container in a stringlist @sl.
  Uses SortKey if @bUseSortKeys is true, else uses GetAllValues.
}
procedure BuildKeyList(container: IwbContainerElementRef; var sl: TStringList;
  bUseSortKeys: boolean);
var
  i, n: integer;
  childElement: IwbElement;
  key, adjustedKey: string;
begin
  // loop through children elements
  for i := 0 to Pred(container.ElementCount) do begin
    childElement := container.Elements[i];

    // use sort if bUseSortKeys is true, else use GetAllValues
    if bUseSortKeys then
      key := childElement.SortKey[false]
    else
      key := GetAllValues(childElement);

    // find a non-colliding key
    n := 0;
    adjustedKey := key;
    while (sl.IndexOf(adjustedKey) > -1) do begin
      Inc(n);
      adjustedKey := key + IntToStr(n);
    end;

    // add adjusted key to stringlist
    sl.Add(adjustedKey);
  end;
end;

{
  MergeArray:
  Merges a sorted or unsorted arrray element by comparing element
  keys.  Compares a source array @src, against a master array @mst and
  a destination array @dst.  Returns true if any changes are made.
  Exits before making any changes if @bSingle is true.  Preserves
  deletions if @bDeletions if true.  Tracks @dstRec and @obj for
  calling rcore on element containers in sorted arrays.
}
function MergeArray(src, mst, dst: IwbElement; dstrec: IwbMainRecord;
  obj: ISuperObject; bSingle, bDeletions, bOverride: boolean): boolean;
var
  i, s_ndx, m_ndx, d_ndx: integer;
  se, de: IwbElement;
  slMst, slDst, slSrc: TStringList;
  srcCont, dstCont, mstCont, seCont: IwbContainerElementRef;
  bSorted: boolean;
begin
  Result := false;

  // exit if input array elements can't be treated as a containers
  if not Supports(src, IwbContainerElementRef, srcCont) then
    exit;
  if not Supports(mst, IwbContainerElementRef, mstCont) then
    exit;
  if not Supports(dst, IwbContainerElementRef, dstCont) then
    exit;

  // determine if we're handling a sorted array
  bSorted := IsSorted(src);

  // Build lists of element keys in each array for easy comparison
  slSrc := TStringList.Create;
  slMst := TStringList.Create;
  slDst := TStringList.Create;
  try
    BuildKeyList(srcCont, slSrc, bSorted);
    BuildKeyList(mstCont, slMst, bSorted);
    BuildKeyList(dstCont, slDst, bSorted);

    // ELEMENT DELETION:
    // Remove elements that are in master and destination, but
    // missing from source
    if bDeletions then
      for i := 0 to Pred(slMst.Count) do begin
        s_ndx := slSrc.IndexOf(slMst[i]);

        // element from master isn't in source
        if (s_ndx = -1) then begin
          Result := true;
          // if we're in a treat as single, exit without removing anything
          if bSingle then exit;
          // if element is present in destination, remove it
          d_ndx := slDst.IndexOf(slMst[i]);
          if (d_ndx = -1) then continue;
          if settings.debugArrays then
            Tracker.Write('        > Removing element at '+dst.Path+' with key: '+slMst[i]);
          dstCont.RemoveElement(d_ndx);
          slDst.Delete(d_ndx);
        end;
      end;

    // ELEMENT ADDITION:
    // Copy array elements in source that aren't in master
    // or destination
    for i := 0 to Pred(slSrc.Count) do begin
      d_ndx := slDst.IndexOf(slSrc[i]);
      m_ndx := slMst.IndexOf(slSrc[i]);
      se := srcCont.Elements[i];


      if (d_ndx = -1) and ((m_ndx = -1) or bOverride) then begin
        Result := true;
        // if we're in a treat as single, exit without adding anything
        if bSingle then exit;
        // add element to destination
        if settings.debugArrays then
          Tracker.Write('        > Adding element at '+dst.Path+' with key: '+slSrc[i]);
        de := dstCont.Assign(dstCont.ElementCount, se, false);
        if bSorted then
          slDst.Insert(dstCont.IndexOf(de), slSrc[i])
        else
          slDst.Add(slSrc[i]);
      end

      // Special handling for sorted arrays
      // Traverses elements that may have been modified without their sortkey changing
      else if bSorted and (d_ndx > -1) and Supports(se, IwbContainerElementRef, seCont)
      and (seCont.ElementCount > 0) then begin
        if settings.debugArrays then begin
          Tracker.Write('        > Traversing element '+se.Path+' with key: '+slSrc[i]);
          Tracker.Write('        > Source Element: '+GetAllValues(se));
          Tracker.Write('        > Destination Element: '+GetAllValues(dstCont.Elements[d_ndx]));
        end;
        // traverse element
        try
          Result := rcore(se, GetMasterElement(src, se, dstrec), dstCont.Elements[d_ndx],
            dstrec, GetElementObj(obj, se.Name), bSingle, bDeletions, bOverride);
          if Result and bSingle then
            exit;
        except on x : Exception do begin
            Tracker.Write('      rcore: Exception at '+se.Path+': '+x.Message);
          end;
        end;
      end;
    end;
  finally
    // free lists
    slMst.Free;
    slSrc.Free;
    slDst.Free;
  end;
end;

{ 
  CopyElementValue:
  Copies the edit value of @se to @de.
}
procedure CopyElementValue(se, me, de: IwbElement);
begin
  if not de.IsEditable then begin
    if settings.debugChanges then begin
      Tracker.Write('      Unable to copy element value on '+se.path);
      Tracker.Write('      Element is not editable');
    end;
    exit;
  end;

  if Assigned(me) and settings.debugChanges then begin
    if (not settings.debugTraversal) then
      Tracker.Write('      '+se.Path);
    Tracker.Write('      > Found differing values: '+se.EditValue+', '+me.EditValue);
  end;

  // try to copy element value to destination element from source element
  try
    de.EditValue := se.EditValue;
  except on x : Exception do
    Tracker.Write('      CopyElementValue: Exception '+x.Message);
  end;
end;

{
  CopyLinkedElement:
  Copies the linked element named eLink, and then copies any elements it is
  linked to.
}
procedure CopyLinkedElement(srcCont, dstCont: IwbContainerElementRef;
  eLink: string; obj: ISuperObject; dstRec: IwbMainRecord);
var
  cObj: ISuperObject;
  le, de: IwbElement;
  cLink: string;
begin
  // exit if we reached the first link in a chain
  if (eLink = firstLink) then begin
    if bLinkProcessed then
      exit;
    bLinkProcessed := true;
  end;

  // else try to copy the linked element
  try
    cObj := GetElementObj(obj, eLink);
    le := srcCont.ElementByName[eLink];
    de := dstCont.ElementByName[eLink];
    if Assigned(le) then begin
      if settings.debugLinks then
        Tracker.Write('      Copying linked element '+le.Path);
      if Assigned(de) then
        de.Assign(Low(Integer), le, false)
      else
        dstCont.AddIfMissing(le, true, true, '', '', '');
      // follow chain
      cLink := cObj.S['lf'];
      if cLink <> '' then
        CopyLinkedElement(srcCont, dstCont, cLink, obj, dstRec);
    end;
  except
    on x: Exception do
      Tracker.Write('        CopyLinkedElement: Failed to copy '+eLink+', '+x.Message);
  end;
end;

{
  HandleElement:
  Wrapper function around the logic for recursing into child 
  elements (rcore), handling an array, or copying element values.
}
function HandleElement(se, me, de: IwbElement; dstRec: IwbMainRecord;
  obj: ISuperObject; bSingle, bDeletions, bOverride: boolean): boolean;
var
  srcType, dstType: TSmashType;
  container: IwbContainerElementRef;
  bCanAdd, bIsContainer: boolean;
  seVal, meVal: string;
begin
  Result := false;

  // deftype and elementtype
  srcType := GetSmashType(se);
  dstType := GetSmashType(de);

  // other type information
  bIsContainer := Supports(se, IwbContainerElementRef, container)
    and (container.ElementCount > 0);
  bCanAdd := se.CanAssign(High(Integer), nil, True)
    and not (esNotSuitableToAddTo in se.ElementStates);

  // exit if srcType <> dstType, returning true
  if srcType <> dstType then begin
    if settings.debugSkips then begin
      Tracker.Write('      Source and destination types don''t match');
      Tracker.Write('      '+stToString(srcType)+' != '+stToString(dstType));
      Tracker.Write('      Skipping '+se.Path);
    end;
    Result := True;
    exit;
  end;

  // exit if master element not assigned and not array
  if not Assigned(me) then begin
    if bCanAdd and (srcType in stArrays) then
      me := de
    else begin
      if settings.debugSkips then begin
        Tracker.Write('      Master element not found!');
        Tracker.Write('      Skipping '+se.Path);
      end;
      exit;
    end;
  end;

  // debug messages
  if settings.debugTraversal then
    Tracker.Write('      '+se.Path);
  if settings.debugTypes then begin
    Tracker.Write('      bCanAdd: '+BoolToStr(bCanAdd, true));
    Tracker.Write('      SmashType: '+stToString(srcType));
  end;

  // merge array
  if bCanAdd and (srcType in stArrays) then begin
    if settings.debugTraversal then
      Tracker.Write('         Merging array');
    try
      Result := MergeArray(se, me, de, dstrec, obj, bSingle, bDeletions, bOverride);
    except on x : Exception do
      Tracker.Write('        MergeArray: Exception at '+se.Path+': '+x.Message);
    end;
  end
  // else recurse deeper
  else if bIsContainer and (srcType <> stInteger) then begin
    if settings.debugTraversal then
      Tracker.Write('        Recursing deeper');
    try
      Result := rcore(se, me, de, dstrec, obj, bSingle, bDeletions, bOverride);
    except on x : Exception do
      Tracker.Write('      rcore: Exception at '+se.Path+': '+x.Message);
    end;
  end
  // else copy element value
  else if (srcType in stValues) then begin
    seVal := se.EditValue;
    meVal := me.EditValue;
    if (seVal <> meVal) then begin
      if not bSingle then
        CopyElementValue(se, me, de);
      Result := true;
    end
    else if settings.debugSkips then begin
      Tracker.Write(Format('         Skipping, "%s" = "%s"', [seVal, meVal]));
    end;
  end
  else if settings.debugSkips then begin
    Tracker.Write(Format('         Skipping, %s is not a value type',
      [stToString(srcType)]));
  end;
end;

{
  rcore:
  Recursively copy overridden elements.  Recursively traverses elements,
  comparing between a source element (from an override record) @src, a 
  master element @mst, and a destination element @dst.  Tracks the 
  destination patch record for element copying through @dstRec.  Uses a 
  json tree @obj to determine user settings for traversal.  Uses @bSingle 
  to determine when we're in a "single entity" as specified by the user, 
  and @bDeletions to determine when it's ok to delete removed elements 
  from the destination patch record.
  
  - Uses HandleElementLife to resolve element creation/deletion.
  - Uses HandleElement to handle arrays, recurse deeper, or copy element
    values
}
function rcore(src, mst, dst: IwbElement; dstRec: IwbMainRecord;
  obj: ISuperObject; bSingle, bDeletions, bOverride: boolean): boolean;
var
  i: integer;
  srcCont, dstCont, mstCont: IwbContainerElementRef;
  se, me, de: IwbElement;
  process, eSingle, eDeletions, eOverride: boolean;
  eObj: ISuperObject;
  eLink: string;
begin
  Result := false;

  // prepare containers
  if not Supports(src, IwbContainerElementRef, srcCont) then begin
    if settings.debugSkips then begin
      Tracker.Write('      Source element not a container.');
      Tracker.Write('      Skipping '+src.Path);
    end;
    exit;
  end;
  if not Supports(dst, IwbContainerElementRef, dstCont) then begin
    if settings.debugSkips then begin
      Tracker.Write('      Destination element not a container.');
      Tracker.Write('      Skipping '+src.Path);
    end;
    exit;
  end;
  if not Supports(mst, IwbContainerElementRef, mstCont) then begin
    if settings.debugSkips then begin
      Tracker.Write('      Master element not a container.');
      Tracker.Write('      Skipping '+src.Path);
    end;
    exit;
  end;

  // copy elements from source to destination if missing AND
  // delete elements missing from source if found in master and destination
  Result := HandleElementLife(srcCont, dstCont, mstCont, dstRec, obj, bSingle, bDeletions, bOverride);
  if bSingle and Result then begin
    if settings.debugSingle then
      Tracker.Write('      Single entity change found at '+src.Path);
    exit;
  end;

  // loop through subelements
  for i := 0 to Pred(srcCont.ElementCount) do begin
    // assign source, destination, master elements
    se := srcCont.Elements[i];
    de := dstCont.ElementByName[se.Name];
    me := mstCont.ElementByName[se.Name];

    // skip if destination element not assigned
    if not Assigned(de) then begin
      if settings.debugSkips then begin
        Tracker.Write('      Destination element not found!');
        Tracker.Write('      Skipping '+se.Path);
      end;
      continue;
    end;

    // skip according to setting
    eObj := GetElementObj(obj, se.Name);
    process := Assigned(eObj) and (eObj.I['p'] = 1);
    if not process then begin
      if settings.debugSkips then
        Tracker.Write('      Skipping '+se.Path);
      continue;
    end;

    // set element treat as single entity / ignore deletions booleans
    eSingle := bSingle or (eObj.I['s'] = 1);
    eDeletions := bDeletions or (eObj.I['d'] = 1);
    eOverride := bOverride or (eObj.I['o'] = 1);

    // handle element
    Result := HandleElement(se, me, de, dstRec, eObj, eSingle, eDeletions, eOverride);

    // if we're in a single entity and an element is changed, break
    // we don't need to handle anything anymore
    if bSingle and Result then begin
      if settings.debugSingle then
        Tracker.Write('      Single entity change found at '+se.Path);
      break;
    end;

    // if the element we're processing has the single entity flag set
    // and we're not currently in a single entity, copy entire element
    if eSingle and (not bSingle) and Result then try
      if settings.debugSingle then
        Tracker.Write(Format('      Copying single entity %s', [se.path]));
      de.Assign(Low(Integer), se, false);
    except
      on x: Exception do
        Tracker.Write('        rcore: Failed to copy '+se.Path+', '+x.Message);
    end;

    // if another element is linked to the element being processed
    // and the element being processed has been modified, copy the linked
    // element
    eLink := eObj.S['lf'];
    if Result and (eLink <> '') then begin
      firstLink := eLink;
      bLinkProcessed := false;
      CopyLinkedElement(srcCont, dstCont, eLink, obj, dstRec);
    end;
  end;
end;

end.


================================================
FILE: frontend/msChoicePanel.pas
================================================
unit msChoicePanel;

interface

uses
  SysUtils, Classes, Controls, Dialogs, Graphics, Buttons, StdCtrls, ExtCtrls,
  ImgList, Types,
  // mte components
  mteHelpers,
  // mp components
  msCore;

type
  TSenderCallback = procedure(Sender: TObject) of object;
  TChoicePanel = class(TPanel)
  public
    Selected: boolean;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure ToggleSelect(Sender: TObject);
    procedure SettingChanged(Sender: TObject);
    procedure Deselect;
    procedure Select;
    procedure SetTop(top: Integer);
    procedure SetWidth(width: Integer);
    function GetSetting: TSmashSetting;
    function GetLabel: string;
    procedure SetSelectCallback(callback: TNotifyEvent);
    procedure SetLabel(sig: string);
    procedure AddChoice(choice: TSmashSetting);
  private
    lstChoices: TList;
    ColorUnselected: Integer;
    ColorSelected: Integer;
    lblSig: TLabel;
    cbChoices: TComboBox;
    SelectCallback: TNotifyEvent;
  end;

implementation


{******************************************************************************}
{ TChoicePanel
  A GUI component for interacting with a profile.
}
{******************************************************************************}

constructor TChoicePanel.Create(AOwner: TComponent);
begin
  // set up panel
  inherited Create(AOwner);
  Parent := AOwner as TWinControl;
  Width := (AOwner as TWinControl).ClientWidth;
  Height := 36;
  Left := 0;
  Top := 0;
  ParentBackground := false;
  ParentColor := false;
  ParentDoubleBuffered := false;
  Cursor := crHandPoint;
  Anchors := [akLeft, akTop, akRight];
  Visible := true;

  // set local variables
  Selected := false;
  ColorUnselected := Color;
  ColorSelected := $f0ece4;
  lstChoices := TList.Create;

  // create components
  lblSig := TLabel.Create(self);
  cbChoices := TComboBox.Create(self);

  // set up lblSig
  lblSig.Parent := self;
  lblSig.Top := 10;
  lblSig.Left := 16;
  lblSig.Caption := 'SIGN';
  lblSig.Cursor := crHandPoint;
  lblSig.Align := alCustom;
  lblSig.Anchors := [akLeft, akTop];

  // set up cbGame
  cbChoices.Parent := self;
  cbChoices.Top := 8;
  cbChoices.Left := 75;
  cbChoices.Width := Width - cbChoices.Left - 6;
  cbChoices.Style := csDropDownList;
  cbChoices.Items.Text := '';
  cbChoices.Items.Add('Patch');
  cbChoices.ItemIndex := 0;
  cbChoices.Align := alCustom;
  cbChoices.Anchors := [akLeft, akTop, akRight];

  // set event handlers
  self.OnClick := ToggleSelect;
  lblSig.OnClick := ToggleSelect;
  cbChoices.OnChange := SettingChanged;
end;

destructor TChoicePanel.Destroy;
begin
  lblSig.Free;
  cbChoices.Free;
  lstChoices.Free;
  inherited;
end;

{ EVENT HANDLING }
procedure TChoicePanel.SettingChanged(Sender: TObject);
begin
  if Assigned(SelectCallback) then SelectCallback(self);
end;

procedure TChoicePanel.ToggleSelect(Sender: TObject);
begin
  if Cursor = crHandPoint then begin
    if Selected then Deselect else Select;
    if Assigned(SelectCallback) then SelectCallback(self);
  end;
end;

procedure TChoicePanel.Select;
begin
  Selected := true;
  Color := ColorSelected;
  Repaint;
end;

procedure TChoicePanel.Deselect;
begin
  Selected := false;
  Color := ColorUnselected;
  Repaint;
end;

procedure TChoicePanel.SetTop(top: Integer);
begin
  self.top := top;
end;

procedure TChoicePanel.SetWidth(width: Integer);
begin
  self.width := width;
end;

function TChoicePanel.GetSetting: TSmashSetting;
begin
  Result := nil;
  if cbChoices.ItemIndex = 0 then
    exit;
  Result := TSmashSetting(lstChoices[cbChoices.ItemIndex - 1]);
end;

function TChoicePanel.GetLabel: string;
begin
  Result := lblSig.Caption;
end;

procedure TChoicePanel.SetSelectCallback(callback: TNotifyEvent);
begin
  SelectCallback := callback;
end;

procedure TChoicePanel.SetLabel(sig: string);
begin
  lblSig.Caption := sig;
end;

procedure TChoicePanel.AddChoice(choice: TSmashSetting);
begin
  lstChoices.Add(choice);
  cbChoices.Items.Add(choice.name);
  cbChoices.ItemIndex := 0;
end;

end.


================================================
FILE: frontend/msConfiguration.pas
================================================
unit msConfiguration;

interface

uses
  Classes, wbInterface,
  // mte units
  mteHelpers, RttiIni;

type
  TGameMode = Record
    longName: string;
    gameName: string;
    gameMode: TwbGameMode;
    regName: string;
    appName: string;
    exeName: string;
    appIDs: string;
    bsaOptMode: string;
  end;
  TSettings = class(TObject)
  public
    [IniSection('General')]
    profile: string;
    newProfile: boolean;
    gameMode: integer;
    gamePath: string;
    language: string;
    simpleDictionaryView: boolean;
    simplePluginsView: boolean;
    simpleSplash: boolean;
    [IniSection('Advanced')]
    generalMessageColor: Int64;
    clientMessageColor: Int64;
    loadMessageColor: Int64;
    patchMessageColor: Int64;
    pluginMessageColor: Int64;
    errorMessageColor: Int64;
    logMessageTemplate: string;
    preserveTempPath: boolean;
    allowTagging: boolean;
    smashSound: boolean;
    [IniSection('Patching')]
    patchDirectory: string;
    debugPatchStatus: boolean;
    debugMasters: boolean;
    debugArrays: boolean;
    debugSkips: boolean;
    debugTraversal: boolean;
    debugTypes: boolean;
    debugChanges: boolean;
    debugSingle: boolean;
    debugLinks: boolean;
    buildRefs: boolean;
    preserveITPOs: boolean;
    constructor Create; virtual;
  end;
  TStatistics = class(TObject)
  public
    [IniSection('Statistics')]
    timesRun: integer;
    patchesBuilt: integer;
    pluginsPatched: integer;
    settingsSubmitted: integer;
    recsSubmitted: integer;
    constructor Create; virtual;
  end;
  TProfile = class(TObject)
  public
    name: string;
    gameMode: Integer;
    gamePath: string;
    constructor Create(name: string); virtual;
    procedure Clone(p: TProfile);
    procedure Delete;
    procedure Rename(name: string);
  end;
  TProgramStatus = class(TObject)
  public
    bInitException, bLoadException, bChangeProfile, bForceTerminate,
    bLoaderDone, bInstallUpdate, bUpdatePatchStatus, bClose: boolean;
    GameMode: TGameMode;
    Version: String;
    constructor Create; virtual;
  end;

  procedure DeleteTempPath;
  procedure LoadLanguage;
  function GetLanguageString(name: string): string;
  procedure SaveProfile(var p: TProfile);
  procedure LoadSettings; overload;
  function LoadSettings(path: string): TSettings; overload;
  procedure SaveSettings; overload;
  procedure SaveSettings(var s: TSettings; path: string); overload;
  procedure LoadStatistics;
  procedure SaveStatistics;

var
  settings: TSettings;
  CurrentProfile: TProfile;
  statistics, sessionStatistics: TStatistics;
  language, PathList: TStringList;
  ProgramStatus: TProgramStatus;

const
  // IMPORTANT CONSTANTS
  bTranslationDump = false;

  // GAME MODES
  GameArray: array[1..6] of TGameMode = (
    ( longName: 'Skyrim'; gameName: 'Skyrim'; gameMode: gmTES5;
      regName: 'Skyrim'; appName: 'TES5'; exeName: 'TESV.exe'; appIDs: '72850';
      bsaOptMode: 'sk'; ),
    ( longName: 'Oblivion'; gameName: 'Oblivion'; gameMode: gmTES4;
      regName: 'Oblivion'; appName: 'TES4'; exeName: 'Oblivion.exe';
      appIDs: '22330,900883'; bsaOptMode: 'ob'; ),
    ( longName: 'Fallout New Vegas'; gameName: 'FalloutNV'; gameMode: gmFNV;
      regName: 'FalloutNV'; appName: 'FNV'; exeName: 'FalloutNV.exe';
      appIDs: '22380,2028016'; bsaOptMode: 'fo'; ),
    ( longName: 'Fallout 3'; gameName: 'Fallout3'; gameMode: gmFO3;
      regName: 'Fallout3'; appName: 'FO3'; exeName: 'Fallout3.exe';
      appIDs: '22300,22370'; bsaOptMode: 'fo'; ),
    ( longName: 'Fallout 4'; gameName: 'Fallout4'; gameMode: gmFO4;
      regName: 'Fallout4'; appName: 'FO4'; exeName: 'Fallout4.exe';
      appIDs: '377160'; bsaOptMode: ''; ),
    ( longName: 'Skyrim Special Edition'; gameName: 'Skyrim'; gameMode: gmSSE;
      regName: 'Skyrim Special Edition'; appName: 'SSE';
      exeName: 'SkyrimSE.exe'; appIDs: '489830'; bsaOptMode: ''; )
  );

implementation

uses
  Graphics, SysUtils, Dialogs, ShellAPI, Windows, Registry;

{ TSettings }
constructor TSettings.Create;
begin
  // default settings
  newProfile := true;
  language := 'English';
  simpleDictionaryView := false;
  simplePluginsView := false;
  patchDirectory := wbDataPath;
  generalMessageColor := clGreen;
  loadMessageColor := clPurple;
  clientMessageColor := clBlue;
  patchMessageColor := $000080FF;
  pluginMessageColor := $00484848;
  errorMessageColor := clRed;
  logMessageTemplate := '[{{AppTime}}] ({{Group}}) {{Label}}: {{Text}}';
end;

{ TStatistics constructor }
constructor TStatistics.Create;
begin
  timesRun := 0;
  patchesBuilt := 0;
  pluginsPatched := 0;
  settingsSubmitted := 0;
  recsSubmitted := 0;
end;

{ TProfile }
constructor TProfile.Create(name: string);
begin
  self.name := name;
end;

procedure TProfile.Clone(p: TProfile);
begin
  name := p.name;
  gameMode := p.gameMode;
  gamePath := p.gamePath;
end;

procedure TProfile.Delete;
var
  path: string;
begin
  path := PathList.Values['ProgramPath'] + 'profiles\' + name;
  if DirectoryExists(path) then
    DeleteToRecycleBin(path, false);
end;

procedure TProfile.Rename(name: string);
var
  oldProfilePath, newProfilePath: string;
begin
  // rename old profile folder if necessary
  oldProfilePath := PathList.Values['ProgramPath'] + 'profiles\' + self.name;
  newProfilePath := PathList.Values['ProgramPath'] + 'profiles\' + name;
  if DirectoryExists(oldProfilePath) then
    RenameFile(oldProfilePath, newProfilePath);

  // then change name in the object
  self.name := name;
end;

{ TProgramStatus }
constructor TProgramStatus.Create;
begin
  bInitException  := false;
  bLoadException := false;
  bChangeProfile := false;
  bForceTerminate := false;
  bUpdatePatchStatus := false;
  bClose := false;
  Version := GetVersionMem;
end;

{ CONFIGURATION HELPERS }

procedure DeleteTempPath;
begin
  DeleteDirectory(PathList.Values['TempPath']);
end;

procedure LoadLanguage;
const
  langFile = 'http://raw.githubusercontent.com/matortheeternal/smash/master/frontend/lang/english.lang';
  directions = 'Your english.lang file is missing.  Please download it from GitHub.  ' +
    'After you click OK, a webpage with the file will be opened.  Right-click the ' +
    'page and choose "Save page as", then save it as english.lang in the "lang\" ' +
    'folder where you have MatorSmash.exe installed.';
  accessMessage = 'It looks like Smash doesn''t have permission to read files ' +
    'from disk.  Try running the program as administrator or disabling your antivirus.';
var
  filename: string;
begin
  filename := Format('lang\%s.lang', [settings.language]);
  language := TStringList.Create;
  if (not FileExists(filename)) then begin
    if settings.language <> 'english' then begin
      settings.language := 'english';
      LoadLanguage;
    end
    else if not FileExists('MatorSmash.exe') then
      MessageDlg(accessMessage, mtConfirmation, [mbOk], 0)
    else begin
      MessageDlg(directions, mtConfirmation, [mbOk], 0);
      ForceDirectories(PathList.Values['ProgramPath'] + 'lang\');
      ShellExecute(0, 'open', PChar(langFile), '', '', SW_SHOWNORMAL);
    end;
  end
  else
    language.LoadFromFile(filename);
end;

function GetLanguageString(name: string): string;
begin
  if language.Values[name] <> '' then
    Result := StringReplace(language.Values[name], '#13#10', #13#10, [rfReplaceAll])
  else
    Result := name;
end;

procedure SaveProfile(var p: TProfile);
var
  path: string;
  pSettings: TSettings;
begin
  // get profile path
  path := PathList.Values['ProgramPath'] + 'profiles\' + p.name + '\settings.ini';
  ForceDirectories(ExtractFilePath(path));

  // load settings if they exist, else create them
  if FileExists(path) then
    pSettings := LoadSettings(path)
  else begin
    pSettings := TSettings.Create;
    pSettings.patchDirectory := p.gamePath + 'Data\';
  end;

  // save profile details to settings
  pSettings.profile := p.name;
  pSettings.gameMode := p.gameMode;
  pSettings.gamePath := p.gamePath;
  SaveSettings(pSettings, path);
end;

procedure SaveSettings;
begin
  // user saving settings from options form
  settings.newProfile := false;
  TRttiIni.Save(PathList.Values['ProfilePath'] + 'settings.ini', settings);
end;

procedure SaveSettings(var s: TSettings; path: string);
begin
  TRttiIni.Save(path, s);
end;

procedure LoadSettings;
begin
  settings := TSettings.Create;
  TRttiIni.Load(PathList.Values['ProfilePath'] + 'settings.ini', settings);
end;

function LoadSettings(path: string): TSettings;
begin
  Result := TSettings.Create;
  TRttiIni.Load(path, Result);
end;

procedure SaveStatistics;
begin
  // move session statistics to general statistics
  Inc(statistics.timesRun, sessionStatistics.timesRun);
  Inc(statistics.patchesBuilt, sessionStatistics.patchesBuilt);
  Inc(statistics.pluginsPatched, sessionStatistics.pluginsPatched);
  Inc(statistics.settingsSubmitted, sessionStatistics.settingsSubmitted);
  Inc(statistics.recsSubmitted, sessionStatistics.recsSubmitted);
  // zero out session statistics
  sessionStatistics.timesRun := 0;
  sessionStatistics.patchesBuilt := 0;
  sessionStatistics.settingsSubmitted := 0;
  sessionStatistics.recsSubmitted := 0;
  // save to file
  TRttiIni.Save('statistics.ini', statistics);
end;

procedure LoadStatistics;
begin
  statistics := TStatistics.Create;
  sessionStatistics := TStatistics.Create;
  TRttiIni.Load('statistics.ini', statistics);
end;

initialization
begin
  ProgramStatus := TProgramStatus.Create;
  PathList := TStringList.Create;
end;

finalization
begin
  ProgramStatus.Free;
  PathList.Free;
end;

end.


================================================
FILE: frontend/msConflict.pas
================================================
unit msConflict;

interface

uses
  Classes, SysUtils,
  // mte units
  mteBase,
  // ms units
  msCore,
  // xEdit units
  wbInterface, wbImplementation, wbHelpers;

type
  // States used in InitNode to indicate states a node shall initially have.
  TVirtualNodeInitState = (
    ivsDisabled,
    ivsExpanded,
    ivsHasChildren,
    ivsMultiline,
    ivsSelected,
    ivsFiltered,
    ivsReInit{>>>},
    ivsHidden{<<<}
  );
  TVirtualNodeInitStates = set of TVirtualNodeInitState;

  // navnode flags
  TNavNodeFlag = (
    nnfInjected,
    nnfNotReachable,
    nnfReferencesInjected
  );

  TNavNodeFlags = set of TNavNodeFlag;

  // navnode data
  PNavNodeData = ^TNavNodeData;
  TNavNodeData = record
    Element      : IwbElement;
    Container    : IwbContainer;
    ConflictAll  : TConflictAll;
    ConflictThis : TConflictThis;
    Flags        : TNavNodeFlags;
  end;

  // node flags
  TViewNodeFlag = (
    vnfDontShow,
    vnfIgnore
  );
  TViewNodeFlags = set of TViewNodeFlag;

  // node data
  PViewNodeData = ^TViewNodeData;
  TViewNodeData = record
    Element: IwbElement;
    Container: IwbContainerElementRef;
    ConflictAll: TConflictAll;
    ConflictThis: TConflictThis;
    ViewNodeFlags: TViewNodeFlags;
  end;

  // collections of node datas
  TViewNodeDatas = array[Word] of TViewNodeData;
  PViewNodeDatas = ^TViewNodeDatas;

  TDynViewNodeDatas = array of TViewNodeData;

  // exposed methods
  procedure ConflictLevelForMainRecord(const aMainRecord: IwbMainRecord;
    out aConflictAll: TConflictAll; out aConflictThis: TConflictThis);
  function ConflictLevelForChildNodeDatas(const aNodeDatas: TDynViewNodeDatas;
    aSiblingCompare, aInjected: Boolean): TConflictAll;
  function ConflictLevelForNodeDatas(const aNodeDatas: PViewNodeDatas;
    aNodeCount: Integer; aSiblingCompare, aInjected: Boolean): TConflictAll;
  function ConflictAllForElements(e1, e2: IwbElement; aSiblingCompare,
    aInjected: Boolean): TConflictAll;
  function ConflictThisForMainRecord(aMainRecord: IwbMainRecord): TConflictThis;
  function ConflictAllForMainRecord(aMainRecord: IwbMainRecord): TConflictAll;
  function IsITPO(rec: IwbMainRecord): Boolean;
  function IsITM(rec: IwbMainRecord): Boolean;

implementation

procedure AppendToNodeDatas(var NodeDatas: TDynViewNodeDatas; e: IwbElement);
var
  Container: IwbContainerElementRef;
begin
  SetLength(NodeDatas, Succ(Length(NodeDatas)));
  NodeDatas[Pred(Length(NodeDatas))].Element := e;
  if Supports(e, IwbContainerElementRef, Container) and (Container.ElementCount > 0) then
    NodeDatas[Pred(Length(NodeDatas))].Container := Container;
end;

function ConflictAllForElements(e1, e2: IwbElement; aSiblingCompare,
  aInjected: Boolean): TConflictAll;
var
  NodeDatas: TDynViewNodeDatas;
begin
  // prepare node datas
  AppendToNodeDatas(NodeDatas, e1);
  AppendToNodeDatas(NodeDatas, e2);

  // compute the conflict level
  Result := caUnknown;
  if Length(NodeDatas) > 0 then
    if Assigned(NodeDatas[0].Container) then
      Result := ConflictLevelForChildNodeDatas(NodeDatas, aSiblingCompare, aInjected)
    else
      Result := ConflictLevelForNodeDatas(@NodeDatas[0], Length(NodeDatas), aSiblingCompare, aInjected);
end;

function NodeDatasForMainRecord(const aMainRecord: IwbMainRecord): TDynViewNodeDatas;
var
  Master        : IwbMainRecord;
  Rec           : IwbMainRecord;
  i, j          : Integer;
  Records       : TStringList;
  AnyHidden     : Boolean;
  IsNonOverride : Boolean;
  EditorID      : string;
  FormID        : Cardinal;
  LoadOrder     : Integer;
  Group         : IwbGroupRecord;
  Signature     : TwbSignature;
  plugin        : TPlugin;
  aFile         : IwbFile;
begin
  Assert(wbLoaderDone);
  IsNonOverride := False;
  AnyHidden := False;

  if aMainRecord.Signature = 'GMST' then begin
    IsNonOverride := True;
    EditorID := aMainRecord.EditorID;
    SetLength(Result, PluginsList.Count);
    Master := nil;
    for i := 0 to Pred(PluginsList.Count) do begin
      plugin := TPlugin(PluginsList[i]);
      aFile := plugin._File;
      Group := aFile.GroupBySignature['GMST'];
      if Assigned(Group) then begin
        Rec := Group.MainRecordByEditorID[EditorID];
        if Assigned(Rec) then begin
          if not Assigned(Master) then
            Master := Rec;
          Result[i].Element := Rec;
        end;
      end;
    end;

  end else if (aMainRecord.Signature = 'NAVI') (* or (aMainRecord.Signature = 'TES4') *) then begin
    IsNonOverride := True;
    Signature := aMainRecord.Signature;
    FormID := aMainRecord.FormID;
    LoadOrder := aMainRecord.GetFile.LoadOrder;
    SetLength(Result, 0);
    Master := nil;
    for i := 0 to Pred(PluginsList.Count) do begin
      plugin := TPlugin(PluginsList[i]);
      aFile := plugin._File;
      if aFile.LoadOrder = LoadOrder then begin
        Group := aFile.GroupBySignature[Signature];
        if Assigned(Group) then begin
          Rec := Group.MainRecordByFormID[FormID];
          if Assigned(Rec) then begin
            j := Length(Result);
            SetLength(Result, j+1);
            if not Assigned(Master) then
              Master := Rec;
            Result[j].Element := Rec;
          end;
        end;
      end;
    end;

  end else if (aMainRecord.Signature = 'TES4') then begin
    IsNonOverride := True;
    Signature := aMainRecord.Signature;
    LoadOrder := aMainRecord.GetFile.LoadOrder;
    SetLength(Result, 0);
    Master := nil;
    for i := 0 to Pred(PluginsList.Count) do begin
      plugin := TPlugin(PluginsList[i]);
      aFile := plugin._File;
      if aFile.LoadOrder = LoadOrder then begin
        // header of .dat file, show only itself
        if SameText(ExtractFileExt(aMainRecord.GetFile.FileName), '.dat') and not SameText(ExtractFileExt(aFile.FileName), '.dat') then
          Continue;
        // skip .dat file header by default
        if not SameText(ExtractFileExt(aMainRecord.GetFile.FileName), '.dat') and SameText(ExtractFileExt(aFile.FileName), '.dat') then
          Continue;
        Rec := aFile.Elements[0] as IwbMainRecord;
        if Assigned(Rec) then begin
          j := Length(Result);
          SetLength(Result, j+1);
          if not Assigned(Master) then
            Master := Rec;
          Result[j].Element := Rec;
        end;
      end;
    end;

  end else begin
    Master := aMainRecord.MasterOrSelf;

    SetLength(Result, Succ(Master.OverrideCount));

    AnyHidden := Master.IsHidden;
    if not AnyHidden then
      for i := 0 to Pred(Master.OverrideCount) do begin
        AnyHidden := Master.Overrides[i].IsHidden;
        if AnyHidden then
          Break;
      end;
  end;

  if (Length(Result) > 1) and ({ModGroupsEnabled or }AnyHidden) or IsNonOverride then begin

    Records := TStringList.Create;
    try
      if IsNonOverride then begin
        for i := Low(Result) to High(Result) do
          if Supports(Result[i].Element, IwbMainRecord, Rec) then
             Records.AddObject(Rec._File.FileName, Pointer(Rec));
        Result := nil;
      end else begin
        Records.AddObject(Master._File.FileName, Pointer(Master));
        for i := 0 to Pred(Master.OverrideCount) do begin
          Rec := Master.Overrides[i];
          Records.AddObject(Rec._File.FileName, Pointer(Rec));
        end;
      end;

      {f ModGroupsEnabled then repeat
        MadeChanges := False;
        sl := TStringList.Create;
        try
          for i := 0 to Pred(ModGroups.Count) do begin
            sl.Assign(TStrings(ModGroups.Objects[i]));
            for j := Pred(sl.Count) downto 0 do begin
              k := Records.IndexOf(sl[j]);
              if K > 0 then // >, not >=, never hide the original master
                sl.Objects[j] := TObject(k)
              else
                sl.Delete(j);
            end;
            if sl.Count > 1 then begin
              k := Integer(sl.Objects[0]);
              j := 1;
              if k = 0 then begin
                while (j < sl.Count) and (Integer(sl.Objects[j]) = k + 1) do begin
                  Records.Objects[Integer(sl.Objects[Pred(j)])] := nil;
                  Inc(k);
                  Inc(j);
                end;
                Inc(j);
              end;
              while (j < sl.Count) do begin
                Records.Objects[Integer(sl.Objects[Pred(j)])] := nil;
                Inc(j);
              end;
              for j := Pred(Records.Count) downto 0 do
                if Records.Objects[j] = nil then begin
                  Records.Delete(j);
                  MadeChanges := True;
                end;
            end;
            if Records.Count < 2 then
              Break;
          end;
        finally
          sl.Free;
        end;
      until not MadeChanges;}

      i := 0;
      while (i < Records.Count) and (Records.Count > 1) do
        if IwbElement(Pointer(Records.Objects[i])).IsHidden then
          Records.Delete(i)
        else
          Inc(i);

      SetLength(Result, Records.Count);
      for i := 0 to Pred(Records.Count) do
        with Result[i] do begin
          Rec := IwbMainRecord(Pointer(Records.Objects[i]));
          if i = 0 then
            Master := Rec;

          Container := Rec as IwbContainerElementRef;
          Element := Container;
          if (Container.ElementCount = 0) or (Rec.Signature <> Master.Signature) then
            Container := nil;
        end;

    finally
      FreeAndNil(Records);
    end;

    Exit;
  end;

  Result[0].Element := Master;
  Result[0].Container := Master as IwbContainerElementRef;
  if Master.ElementCount < 1 then
    Result[0].Container := nil;

  for i := 0 to Pred(Master.OverrideCount) do
    with Result[Succ(i)] do begin
      Container := Master.Overrides[i] as IwbContainerElementRef;
      Element := Container;
      if (Container.ElementCount = 0) or (Master.Overrides[i].Signature <> Master.Signature) then
        Container := nil;
    end;
end;

procedure ConflictLevelForMainRecord(const aMainRecord: IwbMainRecord;
  out aConflictAll: TConflictAll; out aConflictThis: TConflictThis);

  procedure Fix(const aMainRecord: IwbMainRecord);
  begin
    with aMainRecord do begin
      ConflictAll := aConflictAll;
      if ConflictThis = ctUnknown then begin
        ConflictThis := ctHiddenByModGroup;
      end;
    end;
  end;

var
  NodeDatas                   : TDynViewNodeDatas;
  i                           : Integer;
  Master                      : IwbMainRecord;
  KeepAliveRoot               : IwbKeepAliveRoot;
begin
  KeepAliveRoot := wbCreateKeepAliveRoot;

  aConflictAll := aMainRecord.ConflictAll;
  aConflictThis := aMainRecord.ConflictThis;

  if aConflictAll > caUnknown then
    Exit;

  Master := aMainRecord.MasterOrSelf;
  if (Master.OverrideCount = 0) and not wbTranslationMode and not (Master.Signature = 'GMST') then begin
    aConflictAll := caOnlyOne;
    aConflictThis := ctOnlyOne;
    aMainRecord.ConflictAll := aConflictAll;
    aMainRecord.ConflictThis := aConflictThis;
  end else begin
    NodeDatas := NodeDatasForMainRecord(aMainRecord);
    if Length(NodeDatas) = 1 then begin
      aConflictAll := caOnlyOne;
      NodeDatas[0].ConflictAll := caOnlyOne;
      NodeDatas[0].ConflictThis := ctOnlyOne;
    {end else if wbQuickShowConflicts and (Length(NodeDatas) = 2) then begin
      aConflictAll := caOverride;
      NodeDatas[0].ConflictAll := caOverride;
      NodeDatas[1].ConflictAll := caOverride;
      NodeDatas[0].ConflictThis := ctMaster;
      NodeDatas[1].ConflictThis := ctOverride;}
    end else
      aConflictAll := ConflictLevelForChildNodeDatas(NodeDatas, False, (aMainRecord.MasterOrSelf.IsInjected and not (aMainRecord.Signature = 'GMST')) );

    for i := Low(NodeDatas) to High(NodeDatas) do
      with NodeDatas[i] do
        if Assigned(Element) then
          with (Element as IwbMainRecord) do begin
            ConflictAll := aConflictAll;
            ConflictThis := NodeDatas[i].ConflictThis;
          end;

    Fix(Master);
    for i := 0 to Pred(Master.OverrideCount) do
      Fix(Master.Overrides[i]);

    aConflictThis := aMainRecord.ConflictThis;
  end;
end;

procedure InitChilds(const aNodeDatas: PViewNodeDatas; aNodeCount: Integer;
  var aChildCount: Cardinal);
var
  NodeData                    : PNavNodeData;
  Container                   : IwbContainer;
  FirstContainer              : IwbContainer;
  SortableContainer           : IwbSortableContainer;
  Element                     : IwbElement;
  i, j, k                     : Integer;
  SortedCount                 : Integer;
  NonSortedCount              : Integer;
  SortedKeys                  : array of TnxFastStringListCS;
  Sortables                   : array of IwbSortableContainer;
  SortKey                     : string;
  LastSortKey                 : string;
  DupCounter                  : Integer;
begin
  SortedCount := 0;
  NonSortedCount := 0;
  FirstContainer := nil;
  for i := 0 to Pred(aNodeCount) do begin
    NodeData := @aNodeDatas[i];
    Container := NodeData.Container;
    if not Assigned(FirstContainer) then
      FirstContainer := Container;
    if Assigned(Container) then
      if Supports(Container, IwbSortableContainer, SortableContainer) and SortableContainer.Sorted then
        Inc(SortedCount)
      else
        Inc(NonSortedCount);
  end;

  if (NonSortedCount > 0) and (SortedCount > 0) then begin
    if Assigned(FirstContainer) then
      ;//PostAddMessage('Warning: Comparing sorted and unsorted entry for "' + FirstContainer.Path + '" in "'+FirstContainer.ContainingMainRecord.Name+'"');
    SortedCount := 0;
  end;

  if SortedCount > 0 then begin
//    Assert(NonSortedCount = 0);

    SetLength(SortedKeys, Succ(aNodeCount));
    for i := Low(SortedKeys) to High(SortedKeys) do begin
      SortedKeys[i] := TnxFastStringListCS.Create;
      SortedKeys[i].Sorted := True;
      SortedKeys[i].Duplicates := dupError;
    end;

    try
      SortedKeys[aNodeCount].Duplicates := dupIgnore;

      SetLength(Sortables, aNodeCount);

      for i := 0 to Pred(aNodeCount) do
        if Supports(aNodeDatas[i].Container, IwbSortableContainer, Sortables[i]) then begin
          SortableContainer := Sortables[i];
          DupCounter := 0;
          LastSortKey := '';
          for j := 0 to Pred(SortableContainer.ElementCount) do begin
            Element := SortableContainer.Elements[j];
            SortKey := Element.SortKey[False];
            if SameStr(LastSortKey, SortKey) then
              Inc(DupCounter)
            else begin
              DupCounter := 0;
              LastSortKey := SortKey;
            end;

            SortKey := SortKey + '<' + IntToHex64(DupCounter, 4) + '>';

            SortedKeys[i].AddObject(SortKey, Pointer(Element));
            SortedKeys[aNodeCount].Add(SortKey);
          end;
        end;

      aChildCount := SortedKeys[aNodeCount].Count;

      for j := 0 to Pred(aChildCount) do begin
        SortKey := SortedKeys[aNodeCount].Strings[j];
        for i := 0 to Pred(aNodeCount) do
          if SortedKeys[i].Find(SortKey, k) then
            IwbElement(Pointer(SortedKeys[i].Objects[k])).SortOrder := j;
      end;

    finally

      for i := Low(SortedKeys) to High(SortedKeys) do
        FreeAndNil(SortedKeys[i]);

    end;

  end
  else
    for i := 0 to Pred(aNodeCount) do begin
      NodeData := @aNodeDatas[i];
      Container := NodeData.Container;

      if Assigned(Container) then begin
        case Container.ElementType of
          etMainRecord, etSubRecordStruct: begin
              aChildCount := (Container.Def as IwbRecordDef).MemberCount;
              Inc(aChildCount, Container.AdditionalElementCount);
              if Cardinal(Container.ElementCount) > aChildCount then begin
                //PostAddMessage('Error: Container.ElementCount {'+IntToStr(Container.ElementCount)+'} > aChildCount {'+IntToStr(aChildCount)+'} for ' + Container.Path + ' in ' + Container.ContainingMainRecord.Name);
                //for j := 0 to Pred(Container.ElementCount) do
                //PostAddMessage('  #'+IntToStr(j)+': ' + Container.Elements[j].Name);
                //Assert(Cardinal(Container.ElementCount) <= aChildCount);
              end;
            end;
          etSubRecordArray, etArray, etStruct, etSubRecord, etValue, etUnion, etStructChapter:
            if aChildCount < Cardinal(Container.ElementCount) then
              aChildCount := Container.ElementCount;
        end;
      end;
    end;
end;

procedure InitNodes(const aNodeDatas: PViewNodeDatas;
  const aParentDatas: PViewNodeDatas;
  aNodeCount: Integer;
  aIndex: Cardinal;
  var aInitialStates: TVirtualNodeInitStates);
var
  NodeData                    : PViewNodeData;
  ParentData                  : PViewNodeData;
  Container                   : IwbContainerElementRef;
  SortableContainer           : IwbSortableContainer;
  i                           : Integer;
begin
  for i := 0 to Pred(aNodeCount) do begin
    NodeData := @aNodeDatas[i];
    ParentData := @aParentDatas[i];

    Container := ParentData.Container;
    if Assigned(Container) then begin
      if Supports(Container, IwbSortableContainer, SortableContainer) and SortableContainer.Sorted then
        NodeData.Element := Container.ElementBySortOrder[aIndex]
      else
        case Container.ElementType of
          etMainRecord, etSubRecordStruct:
            NodeData.Element := Container.ElementBySortOrder[aIndex];
          etSubRecordArray, etArray, etStruct, etSubRecord, etValue, etUnion, etStructChapter:
            if aIndex < Cardinal(Container.ElementCount) then
              NodeData.Element := Container.Elements[aIndex];
        end;
    end;
    if Assigned(NodeData.Element) and NodeData.Element.DontShow then begin
      NodeData.Element := nil;
      Include(NodeData.ViewNodeFlags, vnfDontShow);
    end;
  end;

  aInitialStates := [ivsDisabled];
  for i := 0 to Pred(aNodeCount) do
    with aNodeDatas[i] do begin
      if Assigned(Element) then
        Exclude(aInitialStates, ivsDisabled)
      else
        if Assigned(aParentDatas) and ((vnfIgnore in aParentDatas[i].ViewNodeFlags) or (Assigned(aParentDatas[i].Element) and (aParentDatas[i].Element.ConflictPriority = cpIgnore))) then
          Include(ViewNodeFlags, vnfIgnore);

      if not Assigned(Container) then
        if Supports(Element, IwbContainerElementRef, Container) then begin
          //          if Container.ElementCount = 0 then
          //            Container := nil;
        end;

      if Assigned(Container) then
        if Container.ElementCount > 0 then
          Include(aInitialStates, ivsHasChildren);
    end;
end;

function ConflictLevelForChildNodeDatas(const aNodeDatas: TDynViewNodeDatas;
  aSiblingCompare, aInjected: Boolean): TConflictAll;
var
  ChildCount                  : Cardinal;
  i, j                        : Integer;
  NodeDatas                   : TDynViewNodeDatas;
  InitialStates               : TVirtualNodeInitStates;
  ConflictAll                 : TConflictAll;
  ConflictThis                : TConflictThis;
  Element                     : IwbElement;
begin
  case Length(aNodeDatas) of
    0: Result := caUnknown;
    1: begin
      Result := caOnlyOne;
      aNodeDatas[0].ConflictThis := ctOnlyOne;
    end;
  else
    Result := caNoConflict;
  end;

  if wbTranslationMode then begin
    if Result < caOnlyOne then
      Exit;
  end
  else begin
    if Result < caNoConflict then
      Exit;
  end;

  ChildCount := 0;
  InitChilds(@aNodeDatas[0], Length(aNodeDatas), ChildCount);
  if ChildCount > 0 then
    for i := 0 to Pred(ChildCount) do begin
      NodeDatas := nil;
      SetLength(NodeDatas, Length(aNodeDatas));
      InitialStates := [];
      InitNodes(@NodeDatas[0], @aNodeDatas[0], Length(aNodeDatas), i, InitialStates);
      if not (ivsDisabled in InitialStates) then begin

        if ivsHasChildren in InitialStates then
          ConflictAll := ConflictLevelForChildNodeDatas(NodeDatas, aSiblingCompare, aInjected)
        else
          ConflictAll := ConflictLevelForNodeDatas(@NodeDatas[0], Length(NodeDatas), aSiblingCompare, aInjected);

        if ConflictAll > Result then
          Result := ConflictAll;

        for j := Low(aNodeDatas) to High(aNodeDatas) do
          if NodeDatas[j].ConflictThis > aNodeDatas[j].ConflictThis then
            aNodeDatas[j].ConflictThis := NodeDatas[j].ConflictThis;

      end
      else begin

        ConflictThis := ctNotDefined;

        for j := Low(aNodeDatas) to High(aNodeDatas) do begin
          Element := aNodeDatas[j].Container;
          if Assigned(Element) then
            Break;
        end;

        if Assigned(Element) and (Element.ElementType in [etMainRecord, etSubRecordStruct]) then begin
          j := (Element as IwbContainer).AdditionalElementCount;
          if i >= j then
            with (Element.Def as IwbRecordDef).Members[i - j] do
              if (wbTranslationMode and (ConflictPriority[nil] <> cpTranslate)) or
                (wbTranslationMode and (ConflictPriority[nil] = cpIgnore)) then
                ConflictThis := ctIgnored;
        end;

        for j := Low(aNodeDatas) to High(aNodeDatas) do
          if ConflictThis > aNodeDatas[j].ConflictThis then
            aNodeDatas[j].ConflictThis := ConflictThis;
      end;
    end;
end;

function ConflictLevelForNodeDatas(const aNodeDatas: PViewNodeDatas;
  aNodeCount: Integer; aSiblingCompare, aInjected: Boolean): TConflictAll;
var
  Element                : IwbElement;
  CompareElement         : IwbElement;
  i, j                   : Integer;
  UniqueValues           : TnxFastStringListCS;

  MasterPosition         : Integer;
  FirstElement           : IwbElement;
  FirstElementNotIgnored : IwbElement;
  LastElement            : IwbElement;
  SameAsLast             : Boolean;
  SameAsFirst            : Boolean;
  OverallConflictThis    : TConflictThis;
  Priority               : TwbConflictPriority;
  ThisPriority           : TwbConflictPriority;
  FoundAny               : Boolean;
begin
//  if aSiblingCompare then
//    Priority := cpBenign
//  else
//    Priority := cpNormal;
//  IgnoreConflicts := False;
  FoundAny := False;
  MasterPosition := 0;
  OverallConflictThis := ctUnknown;
  case aNodeCount of
    0: Result := caUnknown;
    1: begin
        Element := aNodeDatas[0].Element;
        if Assigned(Element) then begin
          if Element.ConflictPriority = cpIgnore then
            aNodeDatas[0].ConflictThis := ctIgnored
          else
            aNodeDatas[0].ConflictThis := ctOnlyOne;
        end else
          aNodeDatas[0].ConflictThis := ctNotDefined;
        Result := caOnlyOne;
      end
  else
    LastElement := aNodeDatas[Pred(aNodeCount)].Element;
    FirstElement := aNodeDatas[0].Element;

    UniqueValues := TnxFastStringListCS.Create;
    UniqueValues.Sorted := True;
    UniqueValues.Duplicates := dupIgnore;
    Priority := cpNormal;
    try
      for i := 0 to Pred(aNodeCount) do begin
        Element := aNodeDatas[i].Element;
        if Assigned(Element) then begin
          FoundAny := True;
          Priority := Element.ConflictPriority;
          if Priority = cpNormalIgnoreEmpty then begin
            FirstElement := Element;
            MasterPosition := i;
            for j := Pred(aNodeCount) downto i do begin
              LastElement := aNodeDatas[j].Element;
              if Assigned(LastElement) then
                Break;
            end;
          end;
          if Element.ConflictPriorityCanChange then begin
            for j := Succ(i) to Pred(aNodeCount) do begin
              Element := aNodeDatas[j].Element;
              if Assigned(Element) then begin
                ThisPriority := Element.ConflictPriority;
                if ThisPriority > Priority then
                  Priority := ThisPriority;
              end;
            end;
          end;
          Break;
        end;
      end;

      if aSiblingCompare then
        if Priority > cpBenign then
          Priority := cpBenign;
      if aInjected and (Priority >= cpNormal) then
        Priority := cpCritical;

      if (Priority > cpIgnore) and (not Assigned(FirstElement) or (FirstElement.ConflictPriority = cpIgnore)) then
        FirstElementNotIgnored := nil
      else
        FirstElementNotIgnored := FirstElement;

      for i := 0 to Pred(aNodeCount) do begin
        Element := aNodeDatas[i].Element;
        if Assigned(Element) then begin
          ThisPriority := Element.ConflictPriority;
          if ThisPriority <> cpIgnore then
            UniqueValues.Add(Element.SortKey[True]);
        end else begin
          ThisPriority := Priority;
          if not (vnfIgnore in aNodeDatas[i].ViewNodeFlags) then
            if Priority <> cpNormalIgnoreEmpty then
              UniqueValues.Add('');
        end;

        if (ThisPriority = cpNormalIgnoreEmpty) and not Assigned(Element) then
          aNodeDatas[i].ConflictThis := ctIgnored
        else if ThisPriority = cpIgnore then
          aNodeDatas[i].ConflictThis := ctIgnored
        else if aSiblingCompare then
          aNodeDatas[i].ConflictThis := ctOnlyOne
        else if i = MasterPosition then begin

          if Assigned(Element) then
            aNodeDatas[i].ConflictThis := ctMaster
          else
            aNodeDatas[i].ConflictThis := ctUnknown;

        end else begin
          SameAsLast := (i = Pred(aNodeCount)) or not (
            (Assigned(Element) <> Assigned(LastElement)) or
            (Assigned(Element) and not SameStr(Element.SortKey[True], LastElement.SortKey[True]))
            );

          SameAsFirst := not (
            (Assigned(Element) <> Assigned(FirstElementNotIgnored)) or
            (Assigned(Element) and not SameStr(Element.SortKey[True], FirstElementNotIgnored.SortKey[True]))
            );

          if not SameAsFirst and
             (ThisPriority = cpBenignIfAdded) and
             SameAsLast and  // We are not overriden later
             not Assigned(FirstElementNotIgnored) then begin // The master did not have that element
            ThisPriority := cpBenign;
            Priority := cpBenign;
            SameAsFirst := True;
          end;

          if SameAsFirst then
            aNodeDatas[i].ConflictThis := ctIdenticalToMaster
          else if SameAsLast then
            aNodeDatas[i].ConflictThis := ctConflictWins
          else
            aNodeDatas[i].ConflictThis := ctConflictLoses;
        end;

        if (ThisPriority = cpBenign) and (aNodeDatas[i].ConflictThis > ctConflictBenign) then
          aNodeDatas[i].ConflictThis := ctConflictBenign;

        if aNodeDatas[i].ConflictThis > OverallConflictThis then
          OverallConflictThis := aNodeDatas[i].ConflictThis;
      end;

      case UniqueValues.Count of
        0: Result := caNoConflict;
        1: Result := caNoConflict;
        2: begin
            Element := aNodeDatas[0].Element;
            CompareElement := aNodeDatas[Pred(aNodeCount)].Element;
            if (Assigned(Element) <> Assigned(CompareElement)) or
              (Assigned(Element) and not SameStr(Element.SortKey[True], CompareElement.SortKey[True])) then
              Result := caOverride
            else if (UniqueValues.IndexOf('') >= 0) and Assigned(CompareElement) and (CompareElement.SortKey[True] <> '') then
              Result := caOverride
            else
              Result := caConflict;
          end
      else
        Result := caConflict;
      end;

      if aSiblingCompare and (Result > caConflictBenign) then
        Result := caConflictBenign;

      if not FoundAny then
        for i := 0 to Pred(aNodeCount) do
          aNodeDatas[i].ConflictThis := ctNotDefined;

      if Result > caNoConflict then
        case Priority of
          cpBenign: Result := caConflictBenign;
          cpCritical: begin
              if UniqueValues.Find('', i) then
                UniqueValues.Delete(i);
              if UniqueValues.Count > 1 then
                Result := caConflictCritical;
            end;
        end;

      if Priority > cpBenign then
        if OverallConflictThis > ctOverride then
          with aNodeDatas[Pred(aNodeCount)] do
            if ConflictThis < ctOverride then
              if ConflictThis = ctIdenticalToMaster then
                ConflictThis := ctIdenticalToMasterWinsConflict
              else
                ConflictThis := ctConflictWins;

      if Result in [caNoConflict, caOverride, caConflict] then
        for i := 0 to Pred(aNodeCount) do begin
          case aNodeDatas[i].ConflictThis of
            ctIdenticalToMaster: case Result of
                caNoConflict: ;
                caOverride, caConflict: if i = Pred(aNodeCount) then
                  aNodeDatas[i].ConflictThis := ctIdenticalToMasterWinsConflict
              end;
            ctConflictWins: case Result of
              caNoConflict: aNodeDatas[i].ConflictThis := ctIdenticalToMaster;
              caOverride: aNodeDatas[i].ConflictThis := ctOverride;
              caConflict: ;
            end;
          end;
        end;

      if Result < caConflict then
        for i := 0 to Pred(aNodeCount) do
          if aNodeDatas[i].ConflictThis >= ctIdenticalToMasterWinsConflict then begin
            Result := caConflict;
            Break;
          end;

    finally
      FreeAndNil(UniqueValues);
    end;
  end;
end;

function ConflictThisForMainRecord(aMainRecord: IwbMainRecord): TConflictThis;
var
  ct: TConflictThis;
  ca: TConflictAll;
begin
  ConflictLevelForMainRecord(aMainRecord, ca, ct);
  Result := ct;
end;

function ConflictAllForMainRecord(aMainRecord: IwbMainRecord): TConflictAll;
var
  ct: TConflictThis;
  ca: TConflictAll;
begin
  ConflictLevelForMainRecord(aMainRecord, ca, ct);
  Result := ca;
end;

function IsITPO(rec: IwbMainRecord): Boolean;
var
  mRec, prevOvr, ovr: IwbMainRecord;
  i: Integer;
begin
  // get previous override
  mRec := rec.MasterOrSelf;
  prevovr := mRec;
  for i := 0 to Pred(mRec.OverrideCount) do begin
    ovr := mRec.Overrides[i];
    if ovr.Equals(rec) then
      Break;
    prevovr := ovr;
  end;

  Result := ConflictAllForElements(prevovr, rec, False, False) <= caNoConflict;
end;

function IsITM(rec: IwbMainRecord): Boolean;
const
  ITMConflictArray: set of TConflictThis = [
    ctIdenticalToMaster,
    ctIdenticalToMasterWinsConflict
  ];
begin
  Result := ConflictThisForMainRecord(rec) in ITMConflictArray;
end;

end.


================================================
FILE: frontend/msConflictForm.dfm
================================================
object ConflictForm: TConflictForm
  Left = 0
  Top = 0
  Caption = 'Combine smash settings'
  ClientHeight = 377
  ClientWidth = 709
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnClose = FormClose
  OnCreate = FormCreate
  OnShow = FormShow
  PixelsPerInch = 96
  TextHeight = 13
  object btnOK: TButton
    Left = 545
    Top = 344
    Width = 75
    Height = 25
    Align = alCustom
    Anchors = [akRight, akBottom]
    Caption = 'OK'
    TabOrder = 0
    OnClick = btnOKClick
  end
  object btnCancel: TButton
    Left = 626
    Top = 344
    Width = 75
    Height = 25
    Align = alCustom
    Anchors = [akRight, akBottom]
    Caption = 'Cancel'
    ModalResult = 2
    TabOrder = 1
  end
  object tvRecords: TTreeView
    Left = 301
    Top = 8
    Width = 400
    Height = 330
    Align = alCustom
    Anchors = [akTop, akRight, akBottom]
    DoubleBuffered = True
    Indent = 19
    MultiSelect = True
    ParentDoubleBuffered = False
    ReadOnly = True
    StateImages = StateImages
    TabOrder = 2
    OnCustomDrawItem = tvRecordsCustomDrawItem
    OnMouseMove = tvRecordsMouseMove
  end
  object sbChoices: TScrollBox
    Left = 8
    Top = 8
    Width = 287
    Height = 330
    Align = alCustom
    Anchors = [akLeft, akTop, akRight, akBottom]
    TabOrder = 3
  end
  object FlagIcons: TImageList
    Left = 408
    Top = 24
    Bitmap = {
      494C010103000800540010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
      0000000000003600000028000000400000001000000001002000000000000010
      0000000000000000000000000000000000000000000000000000000000000000
      0000D7D7F8FF7373E6FF3434DBFF2121BEFF2121BEFF2D2DDAFF6B6BE4FFD2D2
      F7FF000000000000000000000000000000000000000000000000000000000000
      0000E4F1E779D7D6B8CCD4BF91F3D2B683FED2B581FED1BD8FF3D5D3B5CCE3F0
      E6790000000000000000000000000000000000000000D1D1D12E4F4F4FB01B1B
      1BE42B2B2BD48282827DF7F7F708000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000F8F8FDFF7373
      E6FF2020B5FF2020B5FF3434DBFF5B5BE2FF5B5BE2FF3D3DDCFF2020B5FF2020
      B5FF6464E3FFF8F8FDFF00000000000000000000000000000000F2F8F33CD9D8
      BACBDCAB6CFEE1974BFFE18F3DFFE18A37FFDF8835FFDD8A39FFD99044FFD4A3
      64FED4D4B6CBF1F7F23C0000000000000000D1D1D12E0C0C0CF3000000FF0000
      00FF000000FF000000FF3B3B3BC4F2F2F20D0000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      00000000000000000000000000000000000000000000F8F8FDFF4242DDFF2020
      B5FF5353E0FFD7D7F8FF00000000000000000000000000000000E2E2F9FF5B5B
      E2FF2020B5FF3D3DDCFFEFEFFCFF0000000000000000F2F8F33CDBCDA5DEE3A1
      58FFE69240FFE58F3AFFE48D39FFE28B37FFE08A36FFDF8834FFDD8733FFDB87
      35FFD7944CFFD3C49DDEF1F7F23C000000004E4E4EB1000000FF4D4D4DB2D7D7
      D728B2B2B24D1A1A1AE5000000FF3A3A3AC5F2F2F20D00000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      000000000000000000000000000000000000000000007373E6FF2020B5FF8282
      E9FF000000000000000000000000FEFEFE03FDFDFE0700000000000000000000
      00009292EBFF2020B5FF6464E3FF0000000000000000DBDABCCBE6A35AFFE994
      41FFE8923EFFE7903CFFE58E3AFFE38D38FFE28B37FFE08935FFDF8834FFDD86
      32FFDC8633FFD6944BFFD4D3B5CB000000001B1B1BE4000000FFD7D7D7280000
      000000000000D9D9D9261B1B1BE4000000FF3A3A3AC5F2F2F20D000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      000000000000000000000000000000000000D7D7F8FF2020B5FF5353E0FF0000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000006464E3FF2020B5FFC8C8F5FFE6F3E879E3B273FEEC9846FFEB95
      41FFEA933FFFE8913DFFEAA560FFF9F7F5FFF8F0E8FFE18B37FFE08935FFDE88
      33FFDD8632FFDA8735FFD3A263FEE3F0E6792B2B2BD4000000FFB3B3B34C0000
      00000000000000000000D9D9D926BABABA45EFEFEF10F3F3F30C000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000007A7AE7FF2020B5FFD2D2F7FF0000
      00000000000000000000FEFEFE0D0000000000000000F4F4FC28000000000000
      000000000000E2E2F9FF2020B5FF6B6BE4FFDDDBBDCCEBA256FFEE9844FFED96
      42FFEB9440FFE9933FFFEBA562FFF9F7F5FFF8F0E8FFE38C38FFE18A36FFE089
      35FFDE8733FFDD8632FFD88F43FFD4D3B5CC8383837C000000FF1A1A1AE5D9D9
      D9260000000000000000C3C3C33C424242BD131313EC262626D97F7F7F80F7F7
      F708000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000003434DBFF3434DBFF000000000000
      0000B9B9F2FFB9B9F2FFB9B9F2FFB9B9F2FFB9B9F2FFB9B9F2FFB9B9F2FFB9B9
      F2FFEFEFFCFF000000004242DDFF2525D6FFDDC89AF3F09D4BFFF09945FFEE97
      43FFED9642FFEB9440FFECA663FFF9F7F5FFF8F0E9FFE48D39FFE28C38FFE18A
      36FFDF8934FFDE8733FFDB8937FFD1BC8DF3F7F7F7083B3B3BC4000000FF1B1B
      1BE4D9D9D926E3E3E31C060606F9000000FF000000FF000000FF000000FF3B3B
      3BC4F2F2F20D0000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000002323C6FF5353E0FF000000000000
      00002121BEFF2020B5FF2020B5FF2020B5FF2020B5FF2020B5FF2020B5FF2020
      B5FFC8C8F5FF000000006464E3FF2121BEFFDFC38FFEF39C49FFF19A46FFEF99
      44FFEE9743FFEC9541FFEEA864FFF9F7F5FFF8F0E9FFE68F3BFFE48D39FFE28B
      37FFE18A36FFDF8834FFDD8734FFD0B480FE00000000F2F2F20D3A3A3AC50000
      00FF1B1B1BE4CECECE31444444BB7171718EE1E1E11EB7B7B7481A1A1AE50000
      00FF3A3A3AC5F2F2F20D00000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000002323C6FF5353E0FF000000000000
      00002020B5FF2020B5FF2020B5FF2020B5FF2020B5FF2020B5FF2020B5FF2020
      B5FFC8C8F5FF000000006464E3FF2121BEFFE0C390FEF49D4AFFF29B47FFF19A
      46FFEF9844FFEE9743FFEFA965FFF9F7F5FFF8F0E9FFE7903CFFE58E3AFFE48D
      39FFE28B37FFE08A35FFDF8835FFD1B581FE0000000000000000F2F2F20D3A3A
      3AC5000000FF1A1A1AE5B8B8B847E1E1E11E7171718E444444BBCECECE311B1B
      1BE4000000FF3A3A3AC5F2F2F20D000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000003D3DDCFF2D2DDAFF000000000000
      0000F8F8FDFFF8F8FDFFEFEFFCFFEFEFFCFFEFEFFCFFEFEFFCFFEFEFFCFFF8F8
      FDFFF8F8FDFF000000003D3DDCFF2525D6FFDFCA9CF3F3A14FFFF39D48FFF29B
      47FFF09A45FFEF9844FFF0B172FFF9F7F5FFF8F0E9FFE8913DFFE7903CFFE58E
      3AFFE38C38FFE28B37FFDF8C3BFFD2BE90F3000000000000000000000000F2F2
      F20D3B3B3BC4000000FF000000FF000000FF000000FF060606F9E3E3E31CD9D9
      D9261B1B1BE4000000FF3B3B3BC4F7F7F7080000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000007373E6FF2020B5FFD2D2F7FF0000
      0000000000000000000000000000F1F1FA0FFAFAFD05F1F1FC32000000000000
      000000000000E2E2F9FF2020B5FF6B6BE4FFDFDDBFCCF1A85BFFF49E4AFFF39C
      48FFF29B47FFF5CBA3FFF9F7F5FFF9F7F5FFF8F0E9FFEA933FFFE8913DFFE68F
      3BFFE58E3AFFE38C38FFDE9548FFD7D5B7CC0000000000000000000000000000
      0000F7F7F7087F7F7F80262626D9131313EC424242BDC3C3C33C000000000000
      0000D9D9D9261A1A1AE5000000FF8383837C0000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      000000000000000000000000000000000000D7D7F8FF2020B5FF5353E0FF0000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000006464E3FF2020B5FFC8C8F5FFE7F3E979E9B879FEF4A14FFFF49D
      49FFF39C48FFF19B46FFF19F51FFF6DEC6FFF8F1E9FFEB9440FFE9933EFFE891
      3DFFE68F3BFFE3903DFFDAA96AFEE4F1E7790000000000000000000000000000
      00000000000000000000F3F3F30CEFEFEF10BABABA45D9D9D926000000000000
      000000000000B3B3B34C000000FF2C2C2CD30000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      000000000000000000000000000000000000000000007A7AE7FF2020B5FF8282
      E9FF000000000000000000000000000000000000000000000000000000000000
      00008B8BEAFF2020B5FF6464E3FF0000000000000000DFDEC0CBEFAD64FFF4A0
      4CFFF49D49FFF39C48FFF19A46FFF09945FFEE9743FFEC9641FFEB9440FFE992
      3EFFE7913EFFE19E55FFD8D7B9CB000000000000000000000000000000000000
      00000000000000000000F
Download .txt
gitextract_wihtrx14/

├── .gitignore
├── ESPs/
│   ├── SmashTestPlugin01.esp
│   ├── SmashTestPlugin02.esp
│   └── SmashTestPlugin03.esp
├── LICENSE.txt
├── README.md
├── design/
│   ├── code snippets/
│   │   ├── GetMasterElement.pas
│   │   ├── Mator Smash v0.9.pas
│   │   └── better build algorithm.pas
│   ├── diagrams/
│   │   └── Mator Smash.vpp
│   └── notes/
│       ├── algorithm problems.txt
│       ├── handling.txt
│       ├── high level design.txt
│       ├── linking explanation.txt
│       └── todos 1024.txt
├── frontend/
│   ├── MatorSmash.dpr
│   ├── MatorSmash.dproj
│   ├── MatorSmash.mes
│   ├── MatorSmash.res
│   ├── ModelSupport_MatorSmash/
│   │   ├── MatorSmash/
│   │   │   └── default.txvpck
│   │   ├── default.txvpck
│   │   ├── msEditForm/
│   │   │   └── default.txvpck
│   │   ├── msFrontend/
│   │   │   └── default.txvpck
│   │   ├── msOptionsForm/
│   │   │   └── default.txvpck
│   │   ├── msProfileForm/
│   │   │   └── default.txvpck
│   │   ├── msProfilePanel/
│   │   │   └── default.txvpck
│   │   ├── msSmashForm/
│   │   │   └── default.txvpck
│   │   ├── msSplashForm/
│   │   │   └── default.txvpck
│   │   └── msThreads/
│   │       └── default.txvpck
│   ├── lang/
│   │   └── english.lang
│   ├── msAlgorithm.pas
│   ├── msChoicePanel.pas
│   ├── msConfiguration.pas
│   ├── msConflict.pas
│   ├── msConflictForm.dfm
│   ├── msConflictForm.pas
│   ├── msCore.pas
│   ├── msEditForm.dfm
│   ├── msEditForm.pas
│   ├── msLoader.pas
│   ├── msOptionsForm.dfm
│   ├── msOptionsForm.pas
│   ├── msPluginSelectionForm.dfm
│   ├── msPluginSelectionForm.pas
│   ├── msPriorityForm.dfm
│   ├── msPriorityForm.pas
│   ├── msProfileForm.dfm
│   ├── msProfileForm.pas
│   ├── msProfilePanel.pas
│   ├── msSettingsManager.dfm
│   ├── msSettingsManager.pas
│   ├── msSmash.pas
│   ├── msSmashForm.dfm
│   ├── msSmashForm.pas
│   ├── msSplashForm.dfm
│   ├── msSplashForm.pas
│   ├── msTagHelper.dfm
│   ├── msTagHelper.pas
│   ├── msTagManager.dfm
│   ├── msTagManager.pas
│   ├── msThreads.pas
│   ├── settings/
│   │   ├── Fallout3/
│   │   │   └── Smash.All.json
│   │   ├── Fallout4/
│   │   │   └── Smash.All.json
│   │   ├── FalloutNV/
│   │   │   └── Smash.All.json
│   │   ├── Oblivion/
│   │   │   ├── Bash.Actors.ACBS.json
│   │   │   ├── Bash.Actors.AIData.json
│   │   │   ├── Bash.Actors.AIPackages.json
│   │   │   ├── Bash.Actors.Animations.json
│   │   │   ├── Bash.Actors.CombatStyle.json
│   │   │   ├── Bash.Actors.DeathItem.json
│   │   │   ├── Bash.Actors.Skeleton.json
│   │   │   ├── Bash.Actors.Spells.json
│   │   │   ├── Bash.Actors.Stats.json
│   │   │   ├── Bash.Body-F.json
│   │   │   ├── Bash.Body-M.json
│   │   │   ├── Bash.Body-Size-F.json
│   │   │   ├── Bash.Body-Size-M.json
│   │   │   ├── Bash.C.Climate.json
│   │   │   ├── Bash.C.Light.json
│   │   │   ├── Bash.C.Music.json
│   │   │   ├── Bash.C.Name.json
│   │   │   ├── Bash.C.Owner.json
│   │   │   ├── Bash.C.RecordFlags.json
│   │   │   ├── Bash.C.Water.json
│   │   │   ├── Bash.Creatures.Blood.json
│   │   │   ├── Bash.Eyes.json
│   │   │   ├── Bash.Factions.json
│   │   │   ├── Bash.Graphics.json
│   │   │   ├── Bash.Hair.json
│   │   │   ├── Bash.Invent.json
│   │   │   ├── Bash.Lev.json
│   │   │   ├── Bash.NPC.Class.json
│   │   │   ├── Bash.NPC.Race.json
│   │   │   ├── Bash.Names.json
│   │   │   ├── Bash.Npc.EyesOnly.json
│   │   │   ├── Bash.Npc.HairOnly.json
│   │   │   ├── Bash.NpcFaces.json
│   │   │   ├── Bash.NpcFacesForceFullImport.json
│   │   │   ├── Bash.R.AddSpells.json
│   │   │   ├── Bash.R.Attributes-F.json
│   │   │   ├── Bash.R.Attributes-M.json
│   │   │   ├── Bash.R.ChangeSpells.json
│   │   │   ├── Bash.R.Description.json
│   │   │   ├── Bash.Relations.json
│   │   │   ├── Bash.Scripts.json
│   │   │   ├── Bash.Sound.json
│   │   │   ├── Bash.SpellStats.json
│   │   │   ├── Bash.Stats.json
│   │   │   ├── Bash.Voice-F.json
│   │   │   ├── Bash.Voice-M.json
│   │   │   └── Smash.All.json
│   │   └── Skyrim/
│   │       ├── Bash.Actors.ACBS.json
│   │       ├── Bash.Actors.AIData.json
│   │       ├── Bash.Actors.AIPackages.json
│   │       ├── Bash.Actors.AIPackagesMerge.json
│   │       ├── Bash.Actors.CombatStyle.json
│   │       ├── Bash.Actors.DeathItem.json
│   │       ├── Bash.Actors.Spells.json
│   │       ├── Bash.Actors.SpellsMerge.json
│   │       ├── Bash.Actors.Stats.json
│   │       ├── Bash.All.json
│   │       ├── Bash.Body-F.json
│   │       ├── Bash.Body-M.json
│   │       ├── Bash.Body-Size-F.json
│   │       ├── Bash.Body-Size-M.json
│   │       ├── Bash.C.Acoustic.json
│   │       ├── Bash.C.Climate.json
│   │       ├── Bash.C.Encounter.json
│   │       ├── Bash.C.ImageSpace.json
│   │       ├── Bash.C.Light.json
│   │       ├── Bash.C.Location.json
│   │       ├── Bash.C.Music.json
│   │       ├── Bash.C.Name.json
│   │       ├── Bash.C.Owner.json
│   │       ├── Bash.C.RecordFlags.json
│   │       ├── Bash.C.Regions.json
│   │       ├── Bash.C.Water.json
│   │       ├── Bash.Delev.json
│   │       ├── Bash.Eyes.json
│   │       ├── Bash.Factions.json
│   │       ├── Bash.Graphics.json
│   │       ├── Bash.Hairs.json
│   │       ├── Bash.Invent.json
│   │       ├── Bash.Lev.json
│   │       ├── Bash.NPC.Class.json
│   │       ├── Bash.NPC.Race.json
│   │       ├── Bash.Names.json
│   │       ├── Bash.NpcFaces.json
│   │       ├── Bash.NpcFacesForceFullImport.json
│   │       ├── Bash.R.AddSpells.json
│   │       ├── Bash.R.ChangeSpells.json
│   │       ├── Bash.R.Description.json
│   │       ├── Bash.R.Head.json
│   │       ├── Bash.R.Skills.json
│   │       ├── Bash.Relations.json
│   │       ├── Bash.Relev.json
│   │       ├── Bash.Scripts.json
│   │       ├── Bash.Sound.json
│   │       ├── Bash.SpellStats.json
│   │       ├── Bash.Stats.json
│   │       ├── Bash.Voice-F.json
│   │       ├── Bash.Voice-M.json
│   │       ├── Skip.json
│   │       ├── Smash.All.json
│   │       ├── Smash.ForceAll.json
│   │       └── Smash.OverrideAll.json
│   ├── smash.rc
│   └── smash.res
└── lib/
    ├── Imaging/
    │   ├── Imaging.pas
    │   ├── ImagingBitmap.pas
    │   ├── ImagingCanvases.pas
    │   ├── ImagingClasses.pas
    │   ├── ImagingColors.pas
    │   ├── ImagingComponents.pas
    │   ├── ImagingDds.pas
    │   ├── ImagingFormats.pas
    │   ├── ImagingIO.pas
    │   ├── ImagingNetworkGraphics.pas
    │   ├── ImagingOptions.inc
    │   ├── ImagingTarga.pas
    │   ├── ImagingTypes.pas
    │   ├── ImagingUtility.pas
    │   └── ZLib/
    │       ├── dzlib.pas
    │       ├── imadler.pas
    │       ├── iminfblock.pas
    │       ├── iminfcodes.pas
    │       ├── iminffast.pas
    │       ├── iminftrees.pas
    │       ├── iminfutil.pas
    │       ├── impaszlib.pas
    │       ├── imtrees.pas
    │       ├── imzconf.inc
    │       ├── imzdeflate.pas
    │       ├── imzinflate.pas
    │       ├── imzutil.pas
    │       └── readme.txt
    ├── abbrevia/
    │   ├── MPL-1_1.txt
    │   ├── Readme.html
    │   ├── WavPack License.txt
    │   ├── examples/
    │   │   └── Delphi/
    │   │       ├── Abbrexam.dpr
    │   │       ├── BaseDlgu.pas
    │   │       ├── Basedlgu.dfm
    │   │       ├── CabExt.dpr
    │   │       ├── CabExt1.dfm
    │   │       ├── CabExt1.pas
    │   │       ├── CabFind.dpr
    │   │       ├── CabFind1.dfm
    │   │       ├── CabFind1.pas
    │   │       ├── CabView.dpr
    │   │       ├── CabView1.dfm
    │   │       ├── CabView1.pas
    │   │       ├── ComCtrlsDemo.dpr
    │   │       ├── ComCtrlsMain.dfm
    │   │       ├── ComCtrlsMain.pas
    │   │       ├── CompPad.dpr
    │   │       ├── Contents.dpr
    │   │       ├── Demo.cab
    │   │       ├── ExCBrows.dpr
    │   │       ├── ExCBrowu.dfm
    │   │       ├── ExCBrowu.pas
    │   │       ├── ExCf.dpr
    │   │       ├── ExCf.res
    │   │       ├── ExFilter.dpr
    │   │       ├── ExFiltru.dfm
    │   │       ├── ExFiltru.pas
    │   │       ├── ExZipper.dpr
    │   │       ├── ExZippru.dfm
    │   │       ├── ExZippru.pas
    │   │       ├── FCITest1.dfm
    │   │       ├── FCITest1.pas
    │   │       ├── Finder.dpr
    │   │       ├── MakeCab.dpr
    │   │       ├── MakeCab1.dfm
    │   │       ├── MakeCab1.pas
    │   │       ├── SelfStbv.dpr
    │   │       ├── SelfStub.dpr
    │   │       ├── SlfStbv1.dfm
    │   │       ├── SlfStbv1.pas
    │   │       ├── Streams.dpr
    │   │       ├── Streams1.dfm
    │   │       ├── Streams1.pas
    │   │       ├── StrmBmp.dpr
    │   │       ├── StrmBmpU.dfm
    │   │       ├── StrmBmpU.pas
    │   │       ├── StrmPad.dpr
    │   │       ├── TpZip.RC
    │   │       ├── TpZip.dpr
    │   │       ├── TpZip.r32
    │   │       ├── TpZip31.HLP
    │   │       ├── UContent.dfm
    │   │       ├── UContent.pas
    │   │       ├── UMain.dfm
    │   │       ├── UMain.pas
    │   │       ├── Uexample.dfm
    │   │       ├── Uexample.pas
    │   │       ├── Unzip.dpr
    │   │       ├── Unzip.dproj
    │   │       ├── Unzip.dproj.2007
    │   │       ├── UsingApi.dpr
    │   │       ├── Ustrpad.dfm
    │   │       ├── Ustrpad.pas
    │   │       ├── Uunzip.dfm
    │   │       ├── Uunzip.pas
    │   │       ├── Uzip.dfm
    │   │       ├── Uzip.pas
    │   │       ├── ZipReg.dpr
    │   │       ├── ZipReg.dproj
    │   │       ├── ZipReg.dproj.2007
    │   │       ├── ZipReg1.dfm
    │   │       ├── ZipReg1.pas
    │   │       ├── ZipView.dpr
    │   │       ├── ZipView1.dfm
    │   │       ├── ZipView1.pas
    │   │       ├── Zipper.dpr
    │   │       ├── Zipper.dproj
    │   │       ├── Zipper.dproj.2007
    │   │       ├── dgAbout.dfm
    │   │       ├── dgAbout.pas
    │   │       ├── makesfx.dpr
    │   │       ├── spntst0.dfm
    │   │       ├── spntst0.pas
    │   │       ├── uCfGenDg.dfm
    │   │       ├── uCfGenDg.pas
    │   │       ├── uCfMain.dfm
    │   │       ├── uCfMain.pas
    │   │       ├── uCfNewDg.dfm
    │   │       ├── uCfNewDg.pas
    │   │       ├── ubasedlg.dfm
    │   │       ├── ubasedlg.pas
    │   │       ├── ucomppad.dfm
    │   │       ├── ucomppad.pas
    │   │       ├── udemodlg.dfm
    │   │       ├── udemodlg.pas
    │   │       ├── ufinder.dfm
    │   │       ├── ufinder.pas
    │   │       ├── umakesfx.dfm
    │   │       ├── umakesfx.pas
    │   │       ├── usplash.dfm
    │   │       └── usplash.pas
    │   ├── localization/
    │   │   ├── AbResString.pas.afr
    │   │   ├── AbResString.pas.de
    │   │   ├── AbResString.pas.fr
    │   │   ├── AbResString.pas.nl
    │   │   ├── AbResString.pas.ru
    │   │   └── AbResString.pas.tr
    │   ├── packages/
    │   │   ├── Delphi XE/
    │   │   │   ├── Abbrevia.dpk
    │   │   │   ├── Abbrevia.dproj
    │   │   │   ├── Abbrevia.res
    │   │   │   ├── AbbreviaVCL.dpk
    │   │   │   ├── AbbreviaVCL.dproj
    │   │   │   ├── AbbreviaVCL.res
    │   │   │   ├── AbbreviaVCLDesign.dpk
    │   │   │   ├── AbbreviaVCLDesign.dproj
    │   │   │   └── AbbreviaVCLDesign.res
    │   │   └── Delphi XE.groupproj
    │   └── source/
    │       ├── AbArcTyp.pas
    │       ├── AbBase.pas
    │       ├── AbBitBkt.pas
    │       ├── AbBrowse.pas
    │       ├── AbBseCLX.pas
    │       ├── AbBseVCL.pas
    │       ├── AbBzip2.pas
    │       ├── AbBzip2Typ.pas
    │       ├── AbCBrows.pas
    │       ├── AbCView.pas
    │       ├── AbCabExt.pas
    │       ├── AbCabKit.pas
    │       ├── AbCabMak.pas
    │       ├── AbCabTyp.pas
    │       ├── AbCharset.pas
    │       ├── AbComCtrls.pas
    │       ├── AbComCtrls.res
    │       ├── AbCompnd.pas
    │       ├── AbConst.pas
    │       ├── AbCrtl.pas
    │       ├── AbDefine.inc
    │       ├── AbDfBase.pas
    │       ├── AbDfCryS.pas
    │       ├── AbDfDec.pas
    │       ├── AbDfEnc.pas
    │       ├── AbDfHufD.pas
    │       ├── AbDfInW.pas
    │       ├── AbDfOutW.pas
    │       ├── AbDfPkMg.pas
    │       ├── AbDfStrm.pas
    │       ├── AbDfXlat.pas
    │       ├── AbDlgDir.dfm
    │       ├── AbDlgDir.pas
    │       ├── AbDlgPwd.dfm
    │       ├── AbDlgPwd.pas
    │       ├── AbExcept.pas
    │       ├── AbFciFdi.pas
    │       ├── AbGzTyp.pas
    │       ├── AbHexVw.pas
    │       ├── AbLZMA.pas
    │       ├── AbLZMAStream.pas
    │       ├── AbMeter.pas
    │       ├── AbPPMd.pas
    │       ├── AbPeCol.dfm
    │       ├── AbPeCol.pas
    │       ├── AbPeDir.pas
    │       ├── AbPeFn.pas
    │       ├── AbPePass.pas
    │       ├── AbPeVer.dfm
    │       ├── AbPeVer.pas
    │       ├── AbQCView.pas
    │       ├── AbQCmpnd.pas
    │       ├── AbQDgDir.pas
    │       ├── AbQDgDir.xfm
    │       ├── AbQDgPwd.pas
    │       ├── AbQDgPwd.xfm
    │       ├── AbQHexVw.pas
    │       ├── AbQMeter.pas
    │       ├── AbQPeCol.pas
    │       ├── AbQPeCol.xfm
    │       ├── AbQPeDir.pas
    │       ├── AbQPeFn.pas
    │       ├── AbQPePas.pas
    │       ├── AbQPeVer.pas
    │       ├── AbQPeVer.xfm
    │       ├── AbQView.pas
    │       ├── AbQZView.pas
    │       ├── AbQZpOut.pas
    │       ├── AbReg.pas
    │       ├── AbReg.res
    │       ├── AbRegClx.pas
    │       ├── AbRegLinux.pas
    │       ├── AbRegVcl.pas
    │       ├── AbResString.pas
    │       ├── AbSWStm.pas
    │       ├── AbSelfEx.pas
    │       ├── AbSpanSt.pas
    │       ├── AbTarTyp.pas
    │       ├── AbUnzOutStm.pas
    │       ├── AbUnzPrc.pas
    │       ├── AbUnzper.pas
    │       ├── AbUtils.pas
    │       ├── AbVMStrm.pas
    │       ├── AbView.pas
    │       ├── AbWavPack.pas
    │       ├── AbZBrows.pas
    │       ├── AbZLTyp.pas
    │       ├── AbZView.pas
    │       ├── AbZipExt.pas
    │       ├── AbZipKit.pas
    │       ├── AbZipOut.pas
    │       ├── AbZipOut.res
    │       ├── AbZipPrc.pas
    │       ├── AbZipTyp.pas
    │       ├── AbZipper.pas
    │       ├── COM/
    │       │   ├── Abbrevia.dpr
    │       │   ├── Abbrevia.dproj
    │       │   ├── Abbrevia.res
    │       │   ├── Abbrevia.ridl
    │       │   ├── Abbrevia.tlb
    │       │   ├── Abbrevia_TLB.pas
    │       │   ├── Readme.txt
    │       │   ├── _GZipItem.pas
    │       │   ├── _TarItem.pas
    │       │   ├── _ZipItem.pas
    │       │   └── _ZipKit.pas
    │       ├── Win32/
    │       │   ├── CarrylessRangeCoder.obj
    │       │   ├── LzFind.obj
    │       │   ├── LzFindMt.obj
    │       │   ├── LzmaDec.obj
    │       │   ├── LzmaEnc.obj
    │       │   ├── PPMdContext.obj
    │       │   ├── PPMdSubAllocatorVariantI.obj
    │       │   ├── PPMdVariantI.obj
    │       │   ├── Threads.obj
    │       │   ├── blocksort.obj
    │       │   ├── bzlib.obj
    │       │   ├── compress.obj
    │       │   ├── decompress.obj
    │       │   ├── huffman.obj
    │       │   ├── wv_bits.obj
    │       │   ├── wv_extra1.obj
    │       │   ├── wv_extra2.obj
    │       │   ├── wv_float.obj
    │       │   ├── wv_metadata.obj
    │       │   ├── wv_pack.obj
    │       │   ├── wv_tags.obj
    │       │   ├── wv_unpack.obj
    │       │   ├── wv_unpack3.obj
    │       │   ├── wv_words.obj
    │       │   └── wv_wputils.obj
    │       └── Win64/
    │           ├── CarrylessRangeCoder.obj
    │           ├── LzFind.obj
    │           ├── LzFindMt.obj
    │           ├── LzmaDec.obj
    │           ├── LzmaEnc.obj
    │           ├── PPMdContext.obj
    │           ├── PPMdSubAllocatorVariantI.obj
    │           ├── PPMdVariantI.obj
    │           ├── Threads.obj
    │           ├── blocksort.obj
    │           ├── bzlib.obj
    │           ├── compress.obj
    │           ├── decompress.obj
    │           ├── huffman.obj
    │           ├── wv_bits.obj
    │           ├── wv_extra1.obj
    │           ├── wv_extra2.obj
    │           ├── wv_float.obj
    │           ├── wv_metadata.obj
    │           ├── wv_pack.obj
    │           ├── wv_tags.obj
    │           ├── wv_unpack.obj
    │           ├── wv_unpack3.obj
    │           ├── wv_words.obj
    │           └── wv_wputils.obj
    ├── mte/
    │   ├── CRC32.pas
    │   ├── RttiIni.pas
    │   ├── RttiJson.pas
    │   ├── RttiTranslation.pas
    │   ├── W7Taskbar.pas
    │   ├── mteBase.pas
    │   ├── mteChangeLogForm.dfm
    │   ├── mteChangeLogForm.pas
    │   ├── mteHelpers.pas
    │   ├── mteLogger.pas
    │   ├── mteLogging.pas
    │   ├── mtePluginSelectionForm.dfm
    │   ├── mtePluginSelectionForm.pas
    │   ├── mteProgressForm.dfm
    │   ├── mteProgressForm.pas
    │   ├── mteTaskHandler.pas
    │   └── mteTracker.pas
    ├── superobject/
    │   └── superobject.pas
    ├── xedit/
    │   ├── lz4/
    │   │   ├── lz4.pas
    │   │   ├── lz4Common.pas
    │   │   ├── lz4HC.pas
    │   │   ├── lz4frame.pas
    │   │   ├── lz4frame_static.pas
    │   │   ├── lz4io.pas
    │   │   └── xxHash.pas
    │   ├── wbBSA.pas
    │   ├── wbDefines.inc
    │   ├── wbDefinitionsFNV.pas
    │   ├── wbDefinitionsFO3.pas
    │   ├── wbDefinitionsFO4.pas
    │   ├── wbDefinitionsTES3.pas
    │   ├── wbDefinitionsTES4.pas
    │   ├── wbDefinitionsTES5.pas
    │   ├── wbHelpers.pas
    │   ├── wbImplementation.pas
    │   ├── wbInit.pas
    │   ├── wbInterface.pas
    │   ├── wbLocalization.pas
    │   ├── wbSort.pas
    │   ├── wbStreams.pas
    │   └── zlib/
    │       ├── ZLibEx.inc
    │       ├── ZLibExApi.pas
    │       ├── win32/
    │       │   ├── adler32.obj
    │       │   ├── compress.obj
    │       │   ├── crc32.obj
    │       │   ├── deflate.obj
    │       │   ├── infback.obj
    │       │   ├── inffast.obj
    │       │   ├── inflate.obj
    │       │   ├── inftrees.obj
    │       │   └── trees.obj
    │       ├── win64/
    │       │   ├── adler32.obj
    │       │   ├── compress.obj
    │       │   ├── crc32.obj
    │       │   ├── deflate.obj
    │       │   ├── infback.obj
    │       │   ├── inffast.obj
    │       │   ├── inflate.obj
    │       │   ├── inftrees.obj
    │       │   └── trees.obj
    │       └── zlibex.pas
    └── zeosdbo/
        ├── doc/
        │   └── html/
        │       ├── bugreporting.html
        │       ├── buildingtests.html
        │       ├── changes.html
        │       ├── ede.css
        │       ├── installation.html
        │       ├── knownbugs.html
        │       ├── license.html
        │       ├── overview.html
        │       ├── parameters.html
        │       └── readme.html
        ├── packages/
        │   └── DelphiXE/
        │       ├── ZComponent.dpk
        │       ├── ZComponent.dproj
        │       ├── ZComponent.res
        │       ├── ZComponentDesign.dpk
        │       ├── ZComponentDesign.dproj
        │       ├── ZComponentDesign.res
        │       ├── ZCore.dpk
        │       ├── ZCore.dproj
        │       ├── ZCore.res
        │       ├── ZDbc.dpk
        │       ├── ZDbc.dproj
        │       ├── ZDbc.res
        │       ├── ZPackages.inc
        │       ├── ZParseSql.dpk
        │       ├── ZParseSql.dproj
        │       ├── ZParseSql.res
        │       ├── ZPlain.dpk
        │       ├── ZPlain.dproj
        │       ├── ZPlain.res
        │       ├── ZeosDbo.groupproj
        │       └── events good.txt
        └── src/
            ├── Zeos.inc
            ├── ZeosLazarus.inc
            ├── component/
            │   ├── ZAbstractConnection.pas
            │   ├── ZAbstractDataset.pas
            │   ├── ZAbstractRODataset.pas
            │   ├── ZAbstractTable.pas
            │   ├── ZComponent.dcr
            │   ├── ZComponent.inc
            │   ├── ZComponentReg.lrs
            │   ├── ZComponentReg.pas
            │   ├── ZConnection.pas
            │   ├── ZConnectionGroup.pas
            │   ├── ZDataset.pas
            │   ├── ZDatasetUtils.pas
            │   ├── ZGroupedConnection.pas
            │   ├── ZIBEventAlerter.pas
            │   ├── ZPgEventAlerter.pas
            │   ├── ZPropertyEditor.pas
            │   ├── ZQuerySQLEditor.pas
            │   ├── ZROSqlEditor.pas
            │   ├── ZSequence.pas
            │   ├── ZSqlMetadata.pas
            │   ├── ZSqlMonitor.pas
            │   ├── ZSqlProcessor.pas
            │   ├── ZSqlStrings.pas
            │   ├── ZSqlTestForm.pas
            │   ├── ZSqlUpdate.pas
            │   ├── ZStoredProcedure.pas
            │   ├── ZStreamBlob.pas
            │   ├── ZUpdateSqlEditor.dfm
            │   ├── ZUpdateSqlEditor.lfm
            │   ├── ZUpdateSqlEditor.lrs
            │   └── ZUpdateSqlEditor.pas
            ├── core/
            │   ├── ZClasses.pas
            │   ├── ZCollections.pas
            │   ├── ZCompatibility.pas
            │   ├── ZCore.inc
            │   ├── ZEncoding.pas
            │   ├── ZExprParser.pas
            │   ├── ZExprToken.pas
            │   ├── ZExpression.pas
            │   ├── ZFunctions.pas
            │   ├── ZFunctionsConvert.pas
            │   ├── ZFunctionsDateTime.pas
            │   ├── ZFunctionsMath.pas
            │   ├── ZFunctionsOther.pas
            │   ├── ZFunctionsStrings.pas
            │   ├── ZMatchPattern.pas
            │   ├── ZMessages.pas
            │   ├── ZSysUtils.pas
            │   ├── ZTokenizer.pas
            │   ├── ZURL.pas
            │   ├── ZVariables.pas
            │   └── ZVariant.pas
            ├── dbc/
            │   ├── ZDbc.inc
            │   ├── ZDbcASA.pas
            │   ├── ZDbcASAMetadata.pas
            │   ├── ZDbcASAResultSet.pas
            │   ├── ZDbcASAStatement.pas
            │   ├── ZDbcASAUtils.pas
            │   ├── ZDbcAdo.pas
            │   ├── ZDbcAdoMetadata.pas
            │   ├── ZDbcAdoResultSet.pas
            │   ├── ZDbcAdoStatement.pas
            │   ├── ZDbcAdoUtils.pas
            │   ├── ZDbcCache.pas
            │   ├── ZDbcCachedResultSet.pas
            │   ├── ZDbcConnection.pas
            │   ├── ZDbcDbLib.pas
            │   ├── ZDbcDbLibMetadata.pas
            │   ├── ZDbcDbLibResultSet.pas
            │   ├── ZDbcDbLibStatement.pas
            │   ├── ZDbcDbLibUtils.pas
            │   ├── ZDbcGenericResolver.pas
            │   ├── ZDbcInterbase6.pas
            │   ├── ZDbcInterbase6Metadata.pas
            │   ├── ZDbcInterbase6ResultSet.pas
            │   ├── ZDbcInterbase6Statement.pas
            │   ├── ZDbcInterbase6Utils.pas
            │   ├── ZDbcIntfs.pas
            │   ├── ZDbcLogging.pas
            │   ├── ZDbcMetadata.pas
            │   ├── ZDbcMySql.pas
            │   ├── ZDbcMySqlMetadata.pas
            │   ├── ZDbcMySqlResultSet.pas
            │   ├── ZDbcMySqlStatement.pas
            │   ├── ZDbcMySqlUtils.pas
            │   ├── ZDbcOracle.pas
            │   ├── ZDbcOracleMetadata.pas
            │   ├── ZDbcOracleResultSet.pas
            │   ├── ZDbcOracleStatement.pas
            │   ├── ZDbcOracleUtils.pas
            │   ├── ZDbcPooled.pas
            │   ├── ZDbcPostgreSql.pas
            │   ├── ZDbcPostgreSqlMetadata.pas
            │   ├── ZDbcPostgreSqlResultSet.pas
            │   ├── ZDbcPostgreSqlStatement.pas
            │   ├── ZDbcPostgreSqlUtils.pas
            │   ├── ZDbcResultSet.pas
            │   ├── ZDbcResultSetMetadata.pas
            │   ├── ZDbcSqLite.pas
            │   ├── ZDbcSqLiteMetadata.pas
            │   ├── ZDbcSqLiteResultSet.pas
            │   ├── ZDbcSqLiteStatement.pas
            │   ├── ZDbcSqLiteUtils.pas
            │   ├── ZDbcStatement.pas
            │   └── ZDbcUtils.pas
            ├── parsesql/
            │   ├── ZAdoToken.pas
            │   ├── ZGenericSqlAnalyser.pas
            │   ├── ZGenericSqlToken.pas
            │   ├── ZInterbaseAnalyser.pas
            │   ├── ZInterbaseToken.pas
            │   ├── ZMySqlAnalyser.pas
            │   ├── ZMySqlToken.pas
            │   ├── ZOracleAnalyser.pas
            │   ├── ZOracleToken.pas
            │   ├── ZParseSql.inc
            │   ├── ZPostgreSqlAnalyser.pas
            │   ├── ZPostgreSqlToken.pas
            │   ├── ZScriptParser.pas
            │   ├── ZSelectSchema.pas
            │   ├── ZSqLiteAnalyser.pas
            │   ├── ZSqLiteToken.pas
            │   ├── ZSybaseAnalyser.pas
            │   └── ZSybaseToken.pas
            ├── plain/
            │   ├── ZPlain.inc
            │   ├── ZPlainASAConstants.pas
            │   ├── ZPlainASADriver.pas
            │   ├── ZPlainAdo.pas
            │   ├── ZPlainAdoDriver.pas
            │   ├── ZPlainDbLibConstants.pas
            │   ├── ZPlainDbLibDriver.pas
            │   ├── ZPlainDriver.pas
            │   ├── ZPlainFirebirdDriver.pas
            │   ├── ZPlainFirebirdInterbaseConstants.pas
            │   ├── ZPlainLoader.pas
            │   ├── ZPlainMySqlConstants.pas
            │   ├── ZPlainMySqlDriver.pas
            │   ├── ZPlainOracleConstants.pas
            │   ├── ZPlainOracleDriver.pas
            │   ├── ZPlainPostgreSqlDriver.pas
            │   └── ZPlainSqLiteDriver.pas
            ├── repl.awk
            ├── repl.instructions
            └── repl.txt
Copy disabled (too large) Download .json
Condensed preview — 708 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (18,959K chars).
[
  {
    "path": ".gitignore",
    "chars": 1495,
    "preview": "# Uncomment these types if you want even more clean repository. But be careful.\n# It can make harm to an existing projec"
  },
  {
    "path": "LICENSE.txt",
    "chars": 25753,
    "preview": "                          MOZILLA PUBLIC LICENSE\n                                Version 1.1\n\n                          "
  },
  {
    "path": "README.md",
    "chars": 1822,
    "preview": "# smash\nA tool for performing automatic conflict resolution between multiple Bethesda Plugin Files for TES and Fallout g"
  },
  {
    "path": "design/code snippets/GetMasterElement.pas",
    "chars": 1896,
    "preview": "{for j := 0 to ElementCount(ae) - 1 do begin\n  ne := ebi(ae, j);\n  if (SortKey(ne, false) = sk) then begin\n    Result :="
  },
  {
    "path": "design/code snippets/Mator Smash v0.9.pas",
    "chars": 52170,
    "preview": "{\n  Mator Smash v0.9.6\n  created by matortheeternal\n  \n  * DESCRIPTION *\n  This script will make a patch similar to a ba"
  },
  {
    "path": "design/code snippets/better build algorithm.pas",
    "chars": 2956,
    "preview": "procedure LoadElementData(var sl: TStringList; container: IwbContainerElementRef);\nvar\n  innerContainer: IwbContainerEle"
  },
  {
    "path": "design/notes/algorithm problems.txt",
    "chars": 30,
    "preview": "1. Elements with the same name"
  },
  {
    "path": "design/notes/handling.txt",
    "chars": 1041,
    "preview": "Things to handle: ignoring deletions, treat as single entity, priority, linking\n\nIgnoring deletions:\nWhen applied to an "
  },
  {
    "path": "design/notes/high level design.txt",
    "chars": 2320,
    "preview": "Smash\n\nQ: Do we want profiles?\nA: Yes, because a user may have multiple load orders or games they want to use smash with"
  },
  {
    "path": "design/notes/linking explanation.txt",
    "chars": 766,
    "preview": "1. we have a set of plugins\n2. each plugin has a smash setting\n3. each smash setting has a definition for certain record"
  },
  {
    "path": "design/notes/todos 1024.txt",
    "chars": 96,
    "preview": "1. Plugin recommendations \"dictionary\"\n2. Plugin information form (and on main form?)\n3. Backend"
  },
  {
    "path": "frontend/MatorSmash.dpr",
    "chars": 5122,
    "preview": "{*******************************************************************************\n\n     The contents of this file are su"
  },
  {
    "path": "frontend/MatorSmash.dproj",
    "chars": 10685,
    "preview": "\t<Project xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n\t\t<PropertyGroup>\n\t\t\t<ProjectGuid>{12317C9C-736E"
  },
  {
    "path": "frontend/MatorSmash.mes",
    "chars": 7207,
    "preview": "[GeneralSettings]\nMesVersion=4\nHandleExceptions=0\nLinkInCode=1\nAppendMapFileToBinary=1\nNoOwnMadExceptSettings=0\nCheckFil"
  },
  {
    "path": "frontend/ModelSupport_MatorSmash/MatorSmash/default.txvpck",
    "chars": 270,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<nodeSet version=\"1.0\">\n  <view uin=\"b4zfh5af0zf_v\">\n    <property name=\"$default"
  },
  {
    "path": "frontend/ModelSupport_MatorSmash/default.txvpck",
    "chars": 270,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<nodeSet version=\"1.0\">\n  <view uin=\"ea9vm1284dq_v\">\n    <property name=\"$default"
  },
  {
    "path": "frontend/ModelSupport_MatorSmash/msEditForm/default.txvpck",
    "chars": 269,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<nodeSet version=\"1.0\">\n  <view uin=\"njkyjunm3h_v\">\n    <property name=\"$defaultD"
  },
  {
    "path": "frontend/ModelSupport_MatorSmash/msFrontend/default.txvpck",
    "chars": 270,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<nodeSet version=\"1.0\">\n  <view uin=\"n0j337jkpef_v\">\n    <property name=\"$default"
  },
  {
    "path": "frontend/ModelSupport_MatorSmash/msOptionsForm/default.txvpck",
    "chars": 270,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<nodeSet version=\"1.0\">\n  <view uin=\"z6ar60bu6om_v\">\n    <property name=\"$default"
  },
  {
    "path": "frontend/ModelSupport_MatorSmash/msProfileForm/default.txvpck",
    "chars": 270,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<nodeSet version=\"1.0\">\n  <view uin=\"y0bo0tytf3p_v\">\n    <property name=\"$default"
  },
  {
    "path": "frontend/ModelSupport_MatorSmash/msProfilePanel/default.txvpck",
    "chars": 270,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<nodeSet version=\"1.0\">\n  <view uin=\"ac7klwk840k_v\">\n    <property name=\"$default"
  },
  {
    "path": "frontend/ModelSupport_MatorSmash/msSmashForm/default.txvpck",
    "chars": 270,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<nodeSet version=\"1.0\">\n  <view uin=\"d40chv15btm_v\">\n    <property name=\"$default"
  },
  {
    "path": "frontend/ModelSupport_MatorSmash/msSplashForm/default.txvpck",
    "chars": 270,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<nodeSet version=\"1.0\">\n  <view uin=\"xigiykmxj3j_v\">\n    <property name=\"$default"
  },
  {
    "path": "frontend/ModelSupport_MatorSmash/msThreads/default.txvpck",
    "chars": 270,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<nodeSet version=\"1.0\">\n  <view uin=\"y6gq3u7hleh_v\">\n    <property name=\"$default"
  },
  {
    "path": "frontend/lang/english.lang",
    "chars": 6561,
    "preview": "{ TSmashForm }\n{ ## QuickBar ## }\nmsMain_QuickButton_Hint=Quick patch|Apply Smash.All to loaded plugins and #13#10genera"
  },
  {
    "path": "frontend/msAlgorithm.pas",
    "chars": 20262,
    "preview": "unit msAlgorithm;\n\ninterface\n\nuses\n  SysUtils, Classes,\n  // superobject\n  superobject,\n  // mte units\n  mteHelpers, mte"
  },
  {
    "path": "frontend/msChoicePanel.pas",
    "chars": 4042,
    "preview": "unit msChoicePanel;\n\ninterface\n\nuses\n  SysUtils, Classes, Controls, Dialogs, Graphics, Buttons, StdCtrls, ExtCtrls,\n  Im"
  },
  {
    "path": "frontend/msConfiguration.pas",
    "chars": 9552,
    "preview": "unit msConfiguration;\n\ninterface\n\nuses\n  Classes, wbInterface,\n  // mte units\n  mteHelpers, RttiIni;\n\ntype\n  TGameMode ="
  },
  {
    "path": "frontend/msConflict.pas",
    "chars": 30371,
    "preview": "unit msConflict;\n\ninterface\n\nuses\n  Classes, SysUtils,\n  // mte units\n  mteBase,\n  // ms units\n  msCore,\n  // xEdit unit"
  },
  {
    "path": "frontend/msConflictForm.dfm",
    "chars": 33148,
    "preview": "object ConflictForm: TConflictForm\n  Left = 0\n  Top = 0\n  Caption = 'Combine smash settings'\n  ClientHeight = 377\n  Clie"
  },
  {
    "path": "frontend/msConflictForm.pas",
    "chars": 6424,
    "preview": "unit msConflictForm;\n\ninterface\n\nuses\n  Windows, Types, Messages, SysUtils, Variants, Classes, Graphics, Controls,\n  For"
  },
  {
    "path": "frontend/msCore.pas",
    "chars": 53607,
    "preview": "unit msCore;\n\ninterface\n\nuses\n  Classes, Menus, ComCtrls, RegularExpressions,\n  // third party libraries\n  superobject,\n"
  },
  {
    "path": "frontend/msEditForm.dfm",
    "chars": 1809,
    "preview": "object EditForm: TEditForm\n  Left = 0\n  Top = 0\n  ActiveControl = edName\n  Caption = 'Edit patch'\n  ClientHeight = 151\n "
  },
  {
    "path": "frontend/msEditForm.pas",
    "chars": 4466,
    "preview": "unit msEditForm;\n\ninterface\n\nuses\n  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,\n  Dialogs"
  },
  {
    "path": "frontend/msLoader.pas",
    "chars": 18724,
    "preview": "unit msLoader;\n\ninterface\n\nuses\n  Classes,\n  // mte units\n  mteHelpers, mteBase,\n  // mp units\n  msConfiguration;\n\n  { I"
  },
  {
    "path": "frontend/msOptionsForm.dfm",
    "chars": 22958,
    "preview": "object OptionsForm: TOptionsForm\n  Left = 0\n  Top = 0\n  Caption = 'Settings'\n  ClientHeight = 447\n  ClientWidth = 584\n  "
  },
  {
    "path": "frontend/msOptionsForm.pas",
    "chars": 7542,
    "preview": "unit msOptionsForm;\n\ninterface\n\nuses\n  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,\n  Dial"
  },
  {
    "path": "frontend/msPluginSelectionForm.dfm",
    "chars": 2041,
    "preview": "object MiniPluginSelectionForm: TMiniPluginSelectionForm\n  Left = 0\n  Top = 0\n  Caption = 'Plugin selection'\n  ClientHei"
  },
  {
    "path": "frontend/msPluginSelectionForm.pas",
    "chars": 2853,
    "preview": "unit msPluginSelectionForm;\n\ninterface\n\nuses\n  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms"
  },
  {
    "path": "frontend/msPriorityForm.dfm",
    "chars": 1385,
    "preview": "object PriorityForm: TPriorityForm\n  Left = 0\n  Top = 0\n  Caption = 'Change node priority'\n  ClientHeight = 134\n  Client"
  },
  {
    "path": "frontend/msPriorityForm.pas",
    "chars": 641,
    "preview": "unit msPriorityForm;\n\ninterface\n\nuses\n  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,\n  Dia"
  },
  {
    "path": "frontend/msProfileForm.dfm",
    "chars": 701590,
    "preview": "object ProfileForm: TProfileForm\n  Left = 0\n  Top = 0\n  Caption = 'Select Profile'\n  ClientHeight = 467\n  ClientWidth = "
  },
  {
    "path": "frontend/msProfileForm.pas",
    "chars": 8891,
    "preview": "unit msProfileForm;\n\ninterface\n\nuses\n  Windows, Messages, SysUtils, Classes, Controls, Forms, StdCtrls, Graphics,\n  ImgL"
  },
  {
    "path": "frontend/msProfilePanel.pas",
    "chars": 8343,
    "preview": "unit msProfilePanel;\n\ninterface\n\nuses\n  SysUtils, Classes, Controls, Dialogs, Graphics, Buttons, StdCtrls, ExtCtrls,\n  I"
  },
  {
    "path": "frontend/msSettingsManager.dfm",
    "chars": 49572,
    "preview": "object SettingsManager: TSettingsManager\n  Left = 0\n  Top = 0\n  Caption = 'Settings Manager'\n  ClientHeight = 582\n  Clie"
  },
  {
    "path": "frontend/msSettingsManager.pas",
    "chars": 39642,
    "preview": "unit msSettingsManager;\n\ninterface\n\nuses\n  Windows, Types, Messages, SysUtils, Variants, Classes, Graphics, Controls,\n  "
  },
  {
    "path": "frontend/msSmash.pas",
    "chars": 16267,
    "preview": "unit msSmash;\n\ninterface\n\nuses\n  Windows, SysUtils, Classes, ShellAPI, Controls, Dialogs,\n  // superobject\n  superobject"
  },
  {
    "path": "frontend/msSmashForm.dfm",
    "chars": 166676,
    "preview": "object SmashForm: TSmashForm\n  Left = 0\n  Top = 0\n  Caption = 'Mator Smash'\n  ClientHeight = 682\n  ClientWidth = 1264\n  "
  },
  {
    "path": "frontend/msSmashForm.pas",
    "chars": 71736,
    "preview": "unit msSmashForm;\n\ninterface\n\nuses\n  // delphi units\n  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, "
  },
  {
    "path": "frontend/msSplashForm.dfm",
    "chars": 995811,
    "preview": "object SplashForm: TSplashForm\n  Left = 0\n  Top = 0\n  BorderIcons = []\n  BorderStyle = bsSingle\n  Caption = 'Mator Smash"
  },
  {
    "path": "frontend/msSplashForm.pas",
    "chars": 976,
    "preview": "unit msSplashForm;\n\ninterface\n\nuses\n  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,\n  Dialo"
  },
  {
    "path": "frontend/msTagHelper.dfm",
    "chars": 1198,
    "preview": "object TagHelper: TTagHelper\n  Left = 0\n  Top = 0\n  Caption = 'Tag Helper'\n  ClientHeight = 412\n  ClientWidth = 334\n  Co"
  },
  {
    "path": "frontend/msTagHelper.pas",
    "chars": 1672,
    "preview": "unit msTagHelper;\n\ninterface\n\nuses\n  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,\n  Dialog"
  },
  {
    "path": "frontend/msTagManager.dfm",
    "chars": 2567,
    "preview": "object TagManager: TTagManager\n  Left = 0\n  Top = 0\n  Caption = 'Manage Tags'\n  ClientHeight = 312\n  ClientWidth = 434\n "
  },
  {
    "path": "frontend/msTagManager.pas",
    "chars": 4272,
    "preview": "unit msTagManager;\n\ninterface\n\nuses\n  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,\n  Dialo"
  },
  {
    "path": "frontend/msThreads.pas",
    "chars": 7388,
    "preview": "unit msThreads;\n\ninterface\n\nuses\n  Classes, SysUtils, StrUtils, shlObj, Dialogs, ComCtrls,\n  Windows, MMSystem,\n  // sup"
  },
  {
    "path": "frontend/settings/Fallout3/Smash.All.json",
    "chars": 183852,
    "preview": "{\"records\":\"ACHR,ACTI,ADDN,ALCH,AMMO,ANIO,ARMA,ARMO,ASPC,AVIF,BOOK,BPTD,CAMS,CELL,CLAS,CLMT,COBJ,CONT,CPTH,CREA,CSTY,DEB"
  },
  {
    "path": "frontend/settings/Fallout4/Smash.All.json",
    "chars": 511820,
    "preview": "{\"records\":\"ACHR,ACTI,ADDN,AECH,ALCH,AMDL,AMMO,ANIO,AORU,ARMA,ARMO,ARTO,ASPC,ASTP,AVIF,BNDS,BOOK,BPTD,CAMS,CELL,CLAS,CLF"
  },
  {
    "path": "frontend/settings/FalloutNV/Smash.All.json",
    "chars": 208381,
    "preview": "{\"records\":\"ACHR,ACTI,ADDN,ALCH,ALOC,AMEF,AMMO,ANIO,ARMA,ARMO,ASPC,AVIF,BOOK,BPTD,CAMS,CCRD,CDCK,CELL,CHAL,CHIP,CLAS,CLM"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Actors.ACBS.json",
    "chars": 4962,
    "preview": "{\"records\":\"NPC_,CREA\",\"description\":\"Actors.ACBS tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies NPC ACBS configu"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Actors.AIData.json",
    "chars": 4967,
    "preview": "{\"records\":\"NPC_,CREA\",\"description\":\"Actors.AIData tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies NPC AI data.\","
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Actors.AIPackages.json",
    "chars": 4900,
    "preview": "{\"records\":\"NPC_,CREA\",\"description\":\"Actors.AIPackages tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies NPC AI pac"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Actors.Animations.json",
    "chars": 4920,
    "preview": "{\"records\":\"NPC_,CREA\",\"description\":\"Actors.Animations tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies creature o"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Actors.CombatStyle.json",
    "chars": 4875,
    "preview": "{\"records\":\"NPC_,CREA\",\"description\":\"Actors.CombatStyle tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies NPC comba"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Actors.DeathItem.json",
    "chars": 4881,
    "preview": "{\"records\":\"NPC_,CREA\",\"description\":\"Actors.DeathItem tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies creature or"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Actors.Skeleton.json",
    "chars": 4921,
    "preview": "{\"records\":\"NPC_,CREA\",\"description\":\"Actors.Skeleton from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies creature or NPC "
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Actors.Spells.json",
    "chars": 4898,
    "preview": "{\"records\":\"NPC_,CREA\",\"description\":\"Actors.Spells tag from Wrye Bash.\\r\\n\\r\\nUse when the mod modifies creature or NPC"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Actors.Stats.json",
    "chars": 5161,
    "preview": "{\"records\":\"NPC_,CREA\",\"description\":\"Actors.Stats tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies creature or NPC"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Body-F.json",
    "chars": 2903,
    "preview": "{\"records\":\"RACE\",\"description\":\"Body-F tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies female body mesh\\/texture "
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Body-M.json",
    "chars": 2901,
    "preview": "{\"records\":\"RACE\",\"description\":\"Body-M tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies male body mesh\\/texture de"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Body-Size-F.json",
    "chars": 2866,
    "preview": "{\"records\":\"RACE\",\"description\":\"Body-Size-F tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies female body weight\\/h"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Body-Size-M.json",
    "chars": 2864,
    "preview": "{\"records\":\"RACE\",\"description\":\"Body-Size-M tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies male body weight\\/hei"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.C.Climate.json",
    "chars": 1235,
    "preview": "{\"records\":\"CELL\",\"description\":\"C.Climate tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies cell climates.\",\"tree\":"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.C.Light.json",
    "chars": 1346,
    "preview": "{\"records\":\"CELL\",\"description\":\"C.Light tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies cell lighting or fog.\",\"t"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.C.Music.json",
    "chars": 1233,
    "preview": "{\"records\":\"CELL\",\"description\":\"C.Music tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies cell music type.\",\"tree\":"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.C.Name.json",
    "chars": 1226,
    "preview": "{\"records\":\"CELL\",\"description\":\"C.Name tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies cell names.\",\"tree\":{\"reco"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.C.Owner.json",
    "chars": 1256,
    "preview": "{\"records\":\"CELL\",\"description\":\"C.Owner tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies cell ownership.\",\"tree\":{"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.C.RecordFlags.json",
    "chars": 1263,
    "preview": "{\"records\":\"CELL\",\"description\":\"C.RecordFlags tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies the off-limits or d"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.C.Water.json",
    "chars": 1248,
    "preview": "{\"records\":\"CELL\",\"description\":\"C.Water tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies cell water type or level."
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Creatures.Blood.json",
    "chars": 2401,
    "preview": "{\"records\":\"CREA\",\"description\":\"Creatures.Blood tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies the creature bloo"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Eyes.json",
    "chars": 2817,
    "preview": "{\"records\":\"RACE\",\"description\":\"Eyes tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod adds eyes to races.\",\"tree\":{\"records"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Factions.json",
    "chars": 4922,
    "preview": "{\"records\":\"NPC_,CREA\",\"description\":\"Factions tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies creature or NPC fac"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Graphics.json",
    "chars": 27764,
    "preview": "{\"records\":\"ALCH,AMMO,APPA,ARMO,BOOK,BSGN,CLAS,CLOT,CREA,DOOR,EFSH,FLOR,FURN,GRAS,INGR,KEYM,LIGH,LSCR,LTEX,MGEF,MISC,REG"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Hair.json",
    "chars": 2818,
    "preview": "{\"records\":\"RACE\",\"description\":\"Hair tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod adds hairs to races.\",\"tree\":{\"record"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Invent.json",
    "chars": 5425,
    "preview": "{\"records\":\"CREA,NPC_,CONT\",\"description\":\"Invent tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod changes inventories.\",\"tr"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Lev.json",
    "chars": 1305,
    "preview": "{\"records\":\"LVLC,LVSP,LVLI\",\"description\":\"Base setting for Wrye Bash's leveled list handling.\\r\\n\\r\\nWhen used, leveled"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.NPC.Class.json",
    "chars": 2674,
    "preview": "{\"records\":\"NPC_\",\"description\":\"NPC.Class tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod changes the classes of NPCs.\",\"t"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.NPC.Race.json",
    "chars": 2663,
    "preview": "{\"records\":\"NPC_\",\"description\":\"NPC.Race tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies NPC races.\",\"tree\":{\"rec"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Names.json",
    "chars": 39165,
    "preview": "{\"records\":\"ALCH,AMMO,APPA,ARMO,BOOK,BSGN,CELL,CLAS,CLOT,CONT,CREA,DIAL,DOOR,ENCH,EYES,FACT,FLOR,FURN,HAIR,INGR,KEYM,LIG"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Npc.EyesOnly.json",
    "chars": 2681,
    "preview": "{\"records\":\"NPC_\",\"description\":\"Npc.HairOnly tag from Wrye Bash.\\r\\n\\r\\nUse when the mod modifies NPC eyes.\",\"tree\":{\"r"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Npc.HairOnly.json",
    "chars": 2669,
    "preview": "{\"records\":\"NPC_\",\"description\":\"Npc.HairOnly tag from Wrye Bash.\\r\\n\\r\\nUse when the mod modifies NPC hair.\",\"tree\":{\"r"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.NpcFaces.json",
    "chars": 2753,
    "preview": "{\"records\":\"NPC_\",\"description\":\"NpcFaces tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies NPC faces.\",\"tree\":{\"rec"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.NpcFacesForceFullImport.json",
    "chars": 3130,
    "preview": "{\"records\":\"NPC_\",\"description\":\"NpcFacesForceFullImport tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies NPC faces"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.R.AddSpells.json",
    "chars": 2924,
    "preview": "{\"records\":\"RACE\",\"description\":\"R.AddSpells tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod adds spells to racial spell li"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.R.Attributes-F.json",
    "chars": 2904,
    "preview": "{\"records\":\"RACE\",\"description\":\"R.Attributes-F tag from Wrye Bash.\\r\\n\\r\\nUse when the mod modifies racial attributes f"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.R.Attributes-M.json",
    "chars": 2902,
    "preview": "{\"records\":\"RACE\",\"description\":\"R.Attributes-M tag from Wrye Bash.\\r\\n\\r\\nUse when the mod modifies racial attributes f"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.R.ChangeSpells.json",
    "chars": 2953,
    "preview": "{\"records\":\"RACE\",\"description\":\"R.ChangeSpells tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies racial spell list("
  },
  {
    "path": "frontend/settings/Oblivion/Bash.R.Description.json",
    "chars": 2837,
    "preview": "{\"records\":\"RACE\",\"description\":\"R.Description tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies race descriptions.\""
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Relations.json",
    "chars": 668,
    "preview": "{\"records\":\"FACT\",\"description\":\"Relations tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies faction relationships.\""
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Scripts.json",
    "chars": 26956,
    "preview": "{\"records\":\"ALCH,APPA,ARMO,BOOK,CLOT,CONT,CREA,DOOR,FLOR,FURN,INGR,KEYM,LIGH,LVLC,MISC,NPC_,QUST,SGST,SLGM,WEAP,ACTI\",\"d"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Sound.json",
    "chars": 7490,
    "preview": "{\"records\":\"CONT,CREA,DOOR,LIGH,MGEF,WTHR,ACTI\",\"description\":\"Sound tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod replac"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.SpellStats.json",
    "chars": 2382,
    "preview": "{\"records\":\"SPEL\",\"description\":\"SpellStats tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies spell stats.\",\"tree\":{"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Stats.json",
    "chars": 13166,
    "preview": "{\"records\":\"ALCH,APPA,ARMO,BOOK,CLOT,INGR,KEYM,LIGH,MISC,SGST,WEAP,AMMO\",\"description\":\"Stats tag from Wrye Bash.\\r\\n\\r\\"
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Voice-F.json",
    "chars": 2838,
    "preview": "{\"records\":\"RACE\",\"description\":\"Voice-F tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies female voice definitions."
  },
  {
    "path": "frontend/settings/Oblivion/Bash.Voice-M.json",
    "chars": 2836,
    "preview": "{\"records\":\"RACE\",\"description\":\"Voice-M tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies male voice definitions.\","
  },
  {
    "path": "frontend/settings/Oblivion/Smash.All.json",
    "chars": 82667,
    "preview": "{\"records\":\"ACRE,ACTI,ALCH,AMMO,ANIO,APPA,ARMO,BOOK,BSGN,CELL,CLAS,CLMT,CLOT,CONT,CREA,CSTY,DIAL,DOOR,EFSH,ENCH,EYES,FAC"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Actors.ACBS.json",
    "chars": 6785,
    "preview": "{\"records\":\"NPC_\",\"description\":\"Actors.ACBS tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies NPC ACBS configuratio"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Actors.AIData.json",
    "chars": 6784,
    "preview": "{\"records\":\"NPC_\",\"description\":\"Actors.AIData tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies NPC AI data.\",\"tree"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Actors.AIPackages.json",
    "chars": 6741,
    "preview": "{\"records\":\"NPC_\",\"description\":\"Actors.AIPackages tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies NPC AI packages"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Actors.AIPackagesMerge.json",
    "chars": 6914,
    "preview": "{\"records\":\"NPC_\",\"description\":\"An alternative to the Actors.AIPackagesForceAdd tag from Wrye Bash.\\r\\n\\r\\nMator Smash "
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Actors.CombatStyle.json",
    "chars": 6722,
    "preview": "{\"records\":\"NPC_\",\"description\":\"Actors.CombatStyle tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies NPC combat sty"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Actors.DeathItem.json",
    "chars": 6716,
    "preview": "{\"records\":\"NPC_\",\"description\":\"Actors.DeathItem tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies NPC death items."
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Actors.Spells.json",
    "chars": 6728,
    "preview": "{\"records\":\"NPC_\",\"description\":\"Actors.Spells tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies NPC spell lists.\",\""
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Actors.SpellsMerge.json",
    "chars": 6900,
    "preview": "{\"records\":\"NPC_\",\"description\":\"An alternative to the Actors.SpellsForceAdd tag from Wrye Bash.\\r\\n\\r\\nMator Smash cann"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Actors.Stats.json",
    "chars": 6978,
    "preview": "{\"records\":\"NPC_\",\"description\":\"Actors.Stats tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies NPC stats.\",\"tree\":{"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.All.json",
    "chars": 133723,
    "preview": "{\"records\":\"ACTI,ALCH,AMMO,APPA,ARMA,ARMO,ARTO,ASPC,AVIF,BOOK,CELL,CLAS,CONT,DEBR,DIAL,DOOR,EFSH,ENCH,EXPL,FACT,FLOR,FUR"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Body-F.json",
    "chars": 6171,
    "preview": "{\"records\":\"RACE\",\"description\":\"Body-F tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies female body mesh\\/texture "
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Body-M.json",
    "chars": 6169,
    "preview": "{\"records\":\"RACE\",\"description\":\"Body-M tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies male body mesh\\/texture de"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Body-Size-F.json",
    "chars": 6164,
    "preview": "{\"records\":\"RACE\",\"description\":\"Body-Size-F tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies female body weight\\/h"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Body-Size-M.json",
    "chars": 6162,
    "preview": "{\"records\":\"RACE\",\"description\":\"Body-Size-M tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies male body weight\\/hei"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.C.Acoustic.json",
    "chars": 3244,
    "preview": "{\"records\":\"CELL\",\"description\":\"\",\"tree\":{\"records\":[{\"t\":1,\"p\":1,\"n\":\"CELL - Cell\",\"c\":[{\"t\":6,\"n\":\"Record Header\",\"c\""
  },
  {
    "path": "frontend/settings/Skyrim/Bash.C.Climate.json",
    "chars": 3321,
    "preview": "{\"records\":\"CELL\",\"description\":\"C.Climate tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies cell climates.\",\"tree\":"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.C.Encounter.json",
    "chars": 3245,
    "preview": "{\"records\":\"CELL\",\"description\":\"\",\"tree\":{\"records\":[{\"t\":1,\"p\":1,\"n\":\"CELL - Cell\",\"c\":[{\"t\":6,\"n\":\"Record Header\",\"c\""
  },
  {
    "path": "frontend/settings/Skyrim/Bash.C.ImageSpace.json",
    "chars": 3258,
    "preview": "{\"records\":\"CELL\",\"description\":\"\",\"tree\":{\"records\":[{\"t\":1,\"p\":1,\"n\":\"CELL - Cell\",\"d\":1,\"c\":[{\"t\":6,\"n\":\"Record Heade"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.C.Light.json",
    "chars": 3708,
    "preview": "{\"records\":\"CELL\",\"description\":\"C.Light tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies cell lighting or fog.\",\"t"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.C.Location.json",
    "chars": 3244,
    "preview": "{\"records\":\"CELL\",\"description\":\"\",\"tree\":{\"records\":[{\"t\":1,\"p\":1,\"n\":\"CELL - Cell\",\"c\":[{\"t\":6,\"n\":\"Record Header\",\"c\""
  },
  {
    "path": "frontend/settings/Skyrim/Bash.C.Music.json",
    "chars": 3319,
    "preview": "{\"records\":\"CELL\",\"description\":\"C.Music tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies cell music type.\",\"tree\":"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.C.Name.json",
    "chars": 3312,
    "preview": "{\"records\":\"CELL\",\"description\":\"C.Name tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies cell names.\",\"tree\":{\"reco"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.C.Owner.json",
    "chars": 3330,
    "preview": "{\"records\":\"CELL\",\"description\":\"C.Owner tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies cell ownership.\",\"tree\":{"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.C.RecordFlags.json",
    "chars": 3355,
    "preview": "{\"records\":\"CELL\",\"description\":\"C.RecordFlags tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies the off-limits or d"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.C.Regions.json",
    "chars": 3249,
    "preview": "{\"records\":\"CELL\",\"description\":\"\",\"tree\":{\"records\":[{\"t\":1,\"p\":1,\"n\":\"CELL - Cell\",\"c\":[{\"t\":6,\"n\":\"Record Header\",\"c\""
  },
  {
    "path": "frontend/settings/Skyrim/Bash.C.Water.json",
    "chars": 3334,
    "preview": "{\"records\":\"CELL\",\"description\":\"C.Water tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies cell water type or level."
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Delev.json",
    "chars": 2788,
    "preview": "{\"records\":\"LVLI,LVSP,LVLN\",\"description\":\"Delev tag from Wrye Bash.\\r\\n\\r\\nRemoval of entries from the leveled list ent"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Eyes.json",
    "chars": 6108,
    "preview": "{\"records\":\"RACE\",\"description\":\"Eyes tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod adds eyes to races.\",\"tree\":{\"records"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Factions.json",
    "chars": 6733,
    "preview": "{\"records\":\"NPC_\",\"description\":\"Factions tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies NPC factions.\",\"tree\":{\""
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Graphics.json",
    "chars": 45855,
    "preview": "{\"records\":\"ACTI,AMMO,APPA,ARMA,ARMO,ARTO,BOOK,DEBR,DOOR,EFSH,EXPL,FLOR,FURN,GRAS,INGR,LIGH,LSCR,MGEF,MISC,MSTT,PROJ,SCR"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Hairs.json",
    "chars": 6112,
    "preview": "{\"records\":\"RACE\",\"description\":\"Hairs tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod adds hairs to races.\",\"tree\":{\"recor"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Invent.json",
    "chars": 8128,
    "preview": "{\"records\":\"NPC_,CONT\",\"description\":\"Invent tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod changes inventories.\",\"tree\":{"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Lev.json",
    "chars": 2460,
    "preview": "{\"records\":\"LVLI,LVSP,LVLN\",\"description\":\"Base setting for Wrye Bash's leveled list handling.\\r\\n\\r\\nWhen used, leveled"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.NPC.Class.json",
    "chars": 6705,
    "preview": "{\"records\":\"NPC_\",\"description\":\"NPC.Class tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod changes the classes of NPCs.\",\"t"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.NPC.Race.json",
    "chars": 6694,
    "preview": "{\"records\":\"NPC_\",\"description\":\"NPC.Race tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies NPC races.\",\"tree\":{\"rec"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Names.json",
    "chars": 74981,
    "preview": "{\"records\":\"ACTI,AMMO,ARMO,AVIF,BOOK,CLAS,CONT,DIAL,DOOR,ENCH,EXPL,FACT,FLOR,FURN,HAZD,HDPT,INGR,KEYM,LCTN,LIGH,MESG,MGE"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.NpcFaces.json",
    "chars": 6934,
    "preview": "{\"records\":\"NPC_\",\"description\":\"NpcFaces tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies NPC faces.\",\"tree\":{\"rec"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.NpcFacesForceFullImport.json",
    "chars": 7389,
    "preview": "{\"records\":\"NPC_\",\"description\":\"NpcFacesForceFullImport tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies NPC faces"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.R.AddSpells.json",
    "chars": 6216,
    "preview": "{\"records\":\"RACE\",\"description\":\"R.AddSpells tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod adds spells to racial spell li"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.R.ChangeSpells.json",
    "chars": 6245,
    "preview": "{\"records\":\"RACE\",\"description\":\"R.ChangeSpells tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies racial spell list("
  },
  {
    "path": "frontend/settings/Skyrim/Bash.R.Description.json",
    "chars": 6129,
    "preview": "{\"records\":\"RACE\",\"description\":\"R.Description tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies race descriptions.\""
  },
  {
    "path": "frontend/settings/Skyrim/Bash.R.Head.json",
    "chars": 6168,
    "preview": "{\"records\":\"RACE\",\"description\":\"R.Head tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies race heads.\",\"tree\":{\"reco"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.R.Skills.json",
    "chars": 6510,
    "preview": "{\"records\":\"RACE\",\"description\":\"R.Skills tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies race skill bonuses.\",\"tr"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Relations.json",
    "chars": 2166,
    "preview": "{\"records\":\"FACT\",\"description\":\"Relations tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies faction relationships.\""
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Relev.json",
    "chars": 2967,
    "preview": "{\"records\":\"LVLI,LVSP,LVLN\",\"description\":\"Relev tag from Wrye Bash.\\r\\n\\r\\nRe-levelling of entries from the leveled lis"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Scripts.json",
    "chars": 55320,
    "preview": "{\"records\":\"ACHR,ACTI,ARMO,BOOK,CONT,DOOR,FLOR,FURN,INFO,INGR,KEYM,LIGH,MGEF,MISC,NPC_,PACK,PERK,PHZD,QUST,REFR,SCEN,TRE"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Sound.json",
    "chars": 46726,
    "preview": "{\"records\":\"ARMA,ARMO,ASPC,EXPL,IPCT,MGEF,MISC,MSTT,RACE,REVB,SLGM,SNCT,SNDR,SOPM,SOUN,WEAP,WTHR,ACTI\",\"description\":\"So"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.SpellStats.json",
    "chars": 1366,
    "preview": "{\"records\":\"SPEL\",\"description\":\"SpellStats tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies spell stats.\",\"tree\":{"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Stats.json",
    "chars": 17335,
    "preview": "{\"records\":\"AMMO,APPA,ARMO,BOOK,INGR,KEYM,MISC,PROJ,WEAP,ALCH\",\"description\":\"Stats tag from Wrye Bash.\\r\\n\\r\\nUsed when"
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Voice-F.json",
    "chars": 6142,
    "preview": "{\"records\":\"RACE\",\"description\":\"Voice-F tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies female voice definitions."
  },
  {
    "path": "frontend/settings/Skyrim/Bash.Voice-M.json",
    "chars": 6140,
    "preview": "{\"records\":\"RACE\",\"description\":\"Voice-M tag from Wrye Bash.\\r\\n\\r\\nUsed when the mod modifies male voice definitions.\","
  },
  {
    "path": "frontend/settings/Skyrim/Skip.json",
    "chars": 186,
    "preview": "{\"records\":\"\",\"description\":\"Special setting.  Any plugin with this setting will be excluded from patch creation.\",\"tree"
  },
  {
    "path": "frontend/settings/Skyrim/Smash.All.json",
    "chars": 346192,
    "preview": "{\"records\":\"AACT,ACTI,ADDN,ALCH,AMMO,ANIO,APPA,ARMA,ARMO,ARTO,ASPC,ASTP,AVIF,BOOK,BPTD,CAMS,CELL,CLAS,CLDC,CLFM,CLMT,COB"
  },
  {
    "path": "frontend/settings/Skyrim/Smash.ForceAll.json",
    "chars": 346931,
    "preview": "{\"records\":\"AACT,ACTI,ADDN,ALCH,AMMO,ANIO,APPA,ARMA,ARMO,ARTO,ASPC,ASTP,AVIF,BOOK,BPTD,CAMS,CELL,CLAS,CLDC,CLFM,CLMT,COB"
  },
  {
    "path": "frontend/settings/Skyrim/Smash.OverrideAll.json",
    "chars": 346098,
    "preview": "{\"records\":\"AACT,ACTI,ADDN,ALCH,AMMO,ANIO,APPA,ARMA,ARMO,ARTO,ASPC,ASTP,AVIF,BOOK,BPTD,CAMS,CELL,CLAS,CLDC,CLFM,CLMT,COB"
  },
  {
    "path": "frontend/smash.rc",
    "chars": 33,
    "preview": "SMASH WAV \".\\Resources\\smash.wav\""
  },
  {
    "path": "lib/Imaging/Imaging.pas",
    "chars": 141369,
    "preview": "{\n  Vampyre Imaging Library\n  by Marek Mauder \n  http://imaginglib.sourceforge.net\n\n  The contents of this file are used"
  },
  {
    "path": "lib/Imaging/ImagingBitmap.pas",
    "chars": 28013,
    "preview": "{\n  Vampyre Imaging Library\n  by Marek Mauder \n  http://imaginglib.sourceforge.net\n\n  The contents of this file are used"
  },
  {
    "path": "lib/Imaging/ImagingCanvases.pas",
    "chars": 71642,
    "preview": "{\n  Vampyre Imaging Library\n  by Marek Mauder\n  http://imaginglib.sourceforge.net\n\n  The contents of this file are used "
  },
  {
    "path": "lib/Imaging/ImagingClasses.pas",
    "chars": 35383,
    "preview": "{\n  Vampyre Imaging Library\n  by Marek Mauder \n  http://imaginglib.sourceforge.net\n\n  The contents of this file are used"
  },
  {
    "path": "lib/Imaging/ImagingColors.pas",
    "chars": 7847,
    "preview": "{\n  Vampyre Imaging Library\n  by Marek Mauder \n  http://imaginglib.sourceforge.net\n\n  The contents of this file are used"
  },
  {
    "path": "lib/Imaging/ImagingComponents.pas",
    "chars": 42517,
    "preview": "{\n  Vampyre Imaging Library\n  by Marek Mauder \n  http://imaginglib.sourceforge.net\n\n  The contents of this file are used"
  },
  {
    "path": "lib/Imaging/ImagingDds.pas",
    "chars": 43601,
    "preview": "{\n  Vampyre Imaging Library\n  by Marek Mauder\n  http://imaginglib.sourceforge.net\n\n  The contents of this file are used "
  },
  {
    "path": "lib/Imaging/ImagingFormats.pas",
    "chars": 138870,
    "preview": "{\n  Vampyre Imaging Library\n  by Marek Mauder \n  http://imaginglib.sourceforge.net\n\n  The contents of this file are used"
  },
  {
    "path": "lib/Imaging/ImagingIO.pas",
    "chars": 18747,
    "preview": "{\n  Vampyre Imaging Library\n  by Marek Mauder \n  http://imaginglib.sourceforge.net\n\n  The contents of this file are used"
  },
  {
    "path": "lib/Imaging/ImagingNetworkGraphics.pas",
    "chars": 85962,
    "preview": "{\n  Vampyre Imaging Library\n  by Marek Mauder \n  http://imaginglib.sourceforge.net\n\n  The contents of this file are used"
  },
  {
    "path": "lib/Imaging/ImagingOptions.inc",
    "chars": 6694,
    "preview": "{\n  User Options\n  Following defines and options can be changed by user.\n}\n\n{ Source options }\n\n{$DEFINE USE_INLINE}    "
  },
  {
    "path": "lib/Imaging/ImagingTarga.pas",
    "chars": 18511,
    "preview": "{\n  Vampyre Imaging Library\n  by Marek Mauder \n  http://imaginglib.sourceforge.net\n\n  The contents of this file are used"
  },
  {
    "path": "lib/Imaging/ImagingTypes.pas",
    "chars": 24297,
    "preview": "{\n  Vampyre Imaging Library\n  by Marek Mauder \n  http://imaginglib.sourceforge.net\n\n  The contents of this file are used"
  },
  {
    "path": "lib/Imaging/ImagingUtility.pas",
    "chars": 47109,
    "preview": "{\n  Vampyre Imaging Library\n  by Marek Mauder \n  http://imaginglib.sourceforge.net\n\n  The contents of this file are used"
  },
  {
    "path": "lib/Imaging/ZLib/dzlib.pas",
    "chars": 15784,
    "preview": "{*******************************************************}\n{                                                       }\n{   "
  },
  {
    "path": "lib/Imaging/ZLib/imadler.pas",
    "chars": 2459,
    "preview": "Unit imadler;\n\n{\n  adler32.c -- compute the Adler-32 checksum of a data stream\n  Copyright (C) 1995-1998 Mark Adler\n\n  P"
  },
  {
    "path": "lib/Imaging/ZLib/iminfblock.pas",
    "chars": 28159,
    "preview": "Unit iminfblock;\n\n{ infblock.h and\n  infblock.c -- interpret and process block types to last block\n  Copyright (C) 1995-"
  },
  {
    "path": "lib/Imaging/ZLib/iminfcodes.pas",
    "chars": 15099,
    "preview": "Unit iminfcodes;\n\n{ infcodes.c -- process literals and length/distance pairs\n  Copyright (C) 1995-1998 Mark Adler\n\n  Pas"
  },
  {
    "path": "lib/Imaging/ZLib/iminffast.pas",
    "chars": 8894,
    "preview": "Unit iminffast;\n\n{\n  inffast.h and\n  inffast.c -- process literals and length/distance pairs fast\n  Copyright (C) 1995-1"
  },
  {
    "path": "lib/Imaging/ZLib/iminftrees.pas",
    "chars": 28350,
    "preview": "Unit iminftrees;\n\n{ inftrees.h -- header to use inftrees.c\n  inftrees.c -- generate Huffman trees for efficient decoding"
  },
  {
    "path": "lib/Imaging/ZLib/iminfutil.pas",
    "chars": 4869,
    "preview": "Unit iminfutil;\n\n{ types and macros common to blocks and codes\n  Copyright (C) 1995-1998 Mark Adler\n\n   WARNING: this fi"
  },
  {
    "path": "lib/Imaging/ZLib/impaszlib.pas",
    "chars": 17799,
    "preview": "Unit impaszlib;\n\n\n{ Original:\n   zlib.h -- interface of the 'zlib' general purpose compression library\n  version 1.1.0, "
  },
  {
    "path": "lib/Imaging/ZLib/imtrees.pas",
    "chars": 77177,
    "preview": "Unit imtrees;\n\n{$T-}\n{$define ORG_DEBUG}\n{\n  trees.c -- output deflated data using Huffman coding\n  Copyright (C) 1995-1"
  },
  {
    "path": "lib/Imaging/ZLib/imzconf.inc",
    "chars": 649,
    "preview": "{ -------------------------------------------------------------------- }\n\n{$DEFINE MAX_MATCH_IS_258}\n\n{ Compile with -DM"
  },
  {
    "path": "lib/Imaging/ZLib/imzdeflate.pas",
    "chars": 72963,
    "preview": "Unit imzdeflate;\n\n{ Orginal: deflate.h -- internal compression state\n           deflate.c -- compress data using the def"
  },
  {
    "path": "lib/Imaging/ZLib/imzinflate.pas",
    "chars": 22250,
    "preview": "Unit  imzinflate;\n\n{  inflate.c -- zlib interface to inflate modules\n   Copyright (C) 1995-1998 Mark Adler\n\n  Pascal tra"
  },
  {
    "path": "lib/Imaging/ZLib/imzutil.pas",
    "chars": 3892,
    "preview": "Unit imzutil;\n\n{\n  Copyright (C) 1998 by Jacques Nomssi Nzali\n  For conditions of distribution and use, see copyright no"
  },
  {
    "path": "lib/Imaging/ZLib/readme.txt",
    "chars": 5205,
    "preview": "_____________________________________________________________________________\n\nPASZLIB 1.0                              "
  },
  {
    "path": "lib/abbrevia/MPL-1_1.txt",
    "chars": 25755,
    "preview": "                          MOZILLA PUBLIC LICENSE\n                                Version 1.1\n\n                          "
  },
  {
    "path": "lib/abbrevia/Readme.html",
    "chars": 11306,
    "preview": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html lang=\"en-us\">\n<head>\n  <title>Abbrevia v5.0</title"
  },
  {
    "path": "lib/abbrevia/WavPack License.txt",
    "chars": 1558,
    "preview": "               Copyright (c) 1998 - 2009 Conifer Software\n                          All rights reserved.\n\nRedistribution"
  },
  {
    "path": "lib/abbrevia/examples/Delphi/Abbrexam.dpr",
    "chars": 1430,
    "preview": "(* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1\n *\n * The contents of this file are subject to the Mozilla Public"
  },
  {
    "path": "lib/abbrevia/examples/Delphi/BaseDlgu.pas",
    "chars": 1583,
    "preview": "(* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1\n *\n * The contents of this file are subject to the Mozilla Public"
  },
  {
    "path": "lib/abbrevia/examples/Delphi/CabExt.dpr",
    "chars": 1329,
    "preview": "(* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1\n *\n * The contents of this file are subject to the Mozilla Public"
  },
  {
    "path": "lib/abbrevia/examples/Delphi/CabExt1.pas",
    "chars": 3060,
    "preview": "(* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1\n *\n * The contents of this file are subject to the Mozilla Public"
  },
  {
    "path": "lib/abbrevia/examples/Delphi/CabFind.dpr",
    "chars": 1292,
    "preview": "(* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1\n *\n * The contents of this file are subject to the Mozilla Public"
  },
  {
    "path": "lib/abbrevia/examples/Delphi/CabFind1.pas",
    "chars": 3501,
    "preview": "(* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1\n *\n * The contents of this file are subject to the Mozilla Public"
  },
  {
    "path": "lib/abbrevia/examples/Delphi/CabView.dpr",
    "chars": 1016,
    "preview": "(* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1\n *\n * The contents of this file are subject to the Mozilla Public"
  }
]

// ... and 508 more files (download for full content)

About this extraction

This page contains the full source code of the matortheeternal/smash GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 708 files (17.0 MB), approximately 4.5M tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!