コード例 #1
0
ファイル: Spells.cs プロジェクト: rxantos/tesv-snip
 public static void UpdateRecordCount(Plugin plugin)
 {
     int reccount = -1 + plugin.Records.Cast<Rec>().Sum(r => sanitizeCountRecords(r));
     var tes4 = plugin.Records.OfType<Record>().FirstOrDefault(x => x.Name == "TES4");
     if (tes4 != null)
     {
         if (tes4.SubRecords.Count > 0 && tes4.SubRecords[0].Name == "HEDR" && tes4.SubRecords[0].Size >= 8)
         {
             byte[] data = tes4.SubRecords[0].GetData();
             byte[] reccountbytes = TypeConverter.si2h(reccount);
             for (int i = 0; i < 4; i++) data[4 + i] = reccountbytes[i];
             tes4.SubRecords[0].SetData(data);
         }
     }
 }
コード例 #2
0
        public NewMediumLevelRecordEditor(Plugin p, Record r, SubRecord sr, SubrecordStructure ss)
        {
            InitializeComponent();
            Icon = Resources.tesv_ico;
            SuspendLayout();
            this.sr = sr;
            this.ss = ss;
            this.p = p;
            this.r = r;

            // walk each element in standard fashion
            int panelOffset = 0;
            try
            {
                foreach (var elem in ss.elements)
                {
                    Control c = null;
                    if (elem.options != null && elem.options.Length > 1)
                    {
                        c = new OptionsElement();
                    }
                    else if (elem.flags != null && elem.flags.Length > 1)
                    {
                        c = new FlagsElement();
                    }
                    else
                    {
                        switch (elem.type)
                        {
                            case ElementValueType.LString:
                                c = new LStringElement();
                                break;
                            case ElementValueType.FormID:
                                c = new FormIDElement();
                                break;
                            case ElementValueType.Blob:
                                c = new HexElement();
                                break;
                            default:
                                c = new TextElement();
                                break;
                        }
                    }
                    if (c is IElementControl)
                    {
                        var ec = c as IElementControl;
                        ec.formIDLookup = p.GetRecordByID;
                        ec.formIDScan = p.EnumerateRecords;
                        ec.strIDLookup = p.LookupFormStrings;
                        ec.Element = elem;

                        if (elem.repeat > 0)
                        {
                            var ge = new RepeatingElement();
                            c = ge;
                            c.Left = 8;
                            c.Width = fpanel1.Width - 16;
                            c.Top = panelOffset;
                            c.Anchor = c.Anchor | AnchorStyles.Left | AnchorStyles.Right;

                            ge.InnerControl = ec;
                            ge.Element = elem;
                            ec = ge;
                        }
                        else if (elem.optional)
                        {
                            var re = new OptionalElement();
                            c = re;
                            c.Left = 8;
                            c.Width = fpanel1.Width - 16;
                            c.Top = panelOffset;
                            c.Anchor = c.Anchor | AnchorStyles.Left | AnchorStyles.Right;

                            re.InnerControl = ec;
                            re.Element = elem;
                            ec = re;
                            c = re;
                        }
                        else
                        {
                            c.Left = 8;
                            c.Width = fpanel1.Width - 16;
                            c.Top = panelOffset;
                            c.Anchor = c.Anchor | AnchorStyles.Left | AnchorStyles.Right;
                        }
                        c.MinimumSize = c.Size;

                        controlMap.Add(elem, ec);
                        fpanel1.Controls.Add(c);
                        panelOffset = c.Bottom;
                    }
                }

                foreach (Element elem in r.EnumerateElements(sr, true))
                {
                    var es = elem.Structure;

                    IElementControl c;
                    if (controlMap.TryGetValue(es, out c))
                    {
                        if (c is IGroupedElementControl)
                        {
                            var gc = c as IGroupedElementControl;
                            gc.Elements.Add(elem.Data);
                        }
                        else
                        {
                            c.Data = elem.Data;
                        }
                    }
                }
            }
            catch
            {
                strWarnOnSave =
                    "The subrecord doesn't appear to conform to the expected structure.\nThe formatted information may be incorrect.";
                Error.SetError(bSave, strWarnOnSave);
                Error.SetIconAlignment(bSave, ErrorIconAlignment.MiddleLeft);
                AcceptButton = bCancel; // remove save as default button when exception occurs
                CancelButton = bCancel;
                UpdateDefaultButton();
            }
            ResumeLayout();
        }
コード例 #3
0
        /// <summary>
        /// BuildSkyrimDicInTargetLanguage_Click
        /// </summary>
        private void BuildSkyrimDictionnary_Click(object sender, EventArgs e)
        {
            //TESVSnip.Functions.StartCounter();

              Cursor.Current = Cursors.WaitCursor;
              Update();

              try
              {
            translatorHelperContent.ClearMemo();
            CloseProject_Click(sender, new EventArgs());

            Plugin p = new Plugin();

            TESVSnip.Functions.StartCounter();

            string filePath = Path.Combine(Program.gameDataDir, @"Strings\Skyrim_" + translatorHelperContent.GetSourceLanguage() + ".strings");
            if (!File.Exists(filePath))
            {
              MessageBox.Show("Can't find " + filePath, "Translator Helper", MessageBoxButtons.OK, MessageBoxIcon.Error);
              TESVSnip.Functions.StopCounter();
              return;
            }

            filePath = Path.Combine(Program.gameDataDir, @"Strings\Skyrim_" + translatorHelperContent.GetTargetLanguage() + ".strings");
            if (!File.Exists(filePath))
            {
              MessageBox.Show("Can't find " + filePath, "Translator Helper", MessageBoxButtons.OK, MessageBoxIcon.Error);
              TESVSnip.Functions.StopCounter();
              return;
            }

            Properties.Settings.Default.LocalizationName = translatorHelperContent.GetSourceLanguage();
            p.ReloadStrings("Skyrim", Path.Combine(Program.gameDataDir, "Strings"));
            translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.Strings, "Strings", "CREATE");
            translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.DLStrings, "DLStrings", String.Empty);
            translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.ILStrings, "ILStrings", String.Empty);
            p.ReloadStrings("Update", Path.Combine(Program.gameDataDir, "Strings"));
            translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.Strings, "Strings", String.Empty);
            translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.DLStrings, "DLStrings", String.Empty);
            translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.ILStrings, "ILStrings", String.Empty); //"WRITE");

            Properties.Settings.Default.LocalizationName = translatorHelperContent.GetTargetLanguage();
            p.ReloadStrings("Skyrim", Path.Combine(Program.gameDataDir, "Strings"));
            translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.Strings, "Strings", String.Empty); //"CREATE");
            translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.DLStrings, "DLStrings", String.Empty);
            translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.ILStrings, "ILStrings", String.Empty);
            p.ReloadStrings("Update", Path.Combine(Program.gameDataDir, "Strings"));
            translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.Strings, "Strings", String.Empty);
            translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.DLStrings, "DLStrings", String.Empty);
            translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.ILStrings, "ILStrings", "WRITE");

            translatorHelperContent.AddToMemo("Load Strings in " + TESVSnip.Functions.StopCounter() + Environment.NewLine);

            TESVSnip.Functions.StartCounter();
            PluginTree.UpdateRoots();
            OpenPlugin(Path.Combine(Program.gameDataDir, "Skyrim.esm"), false);
            PluginTree.SelectedRecord = PluginTree.TopRecord;
            translatorHelperContent.PluginTree = GetPluginFromNode(PluginTree.SelectedRecord);
            translatorHelperContent.AddToMemo("Load Skyrim.esm in " + TESVSnip.Functions.StopCounter() + Environment.NewLine);

            TESVSnip.Functions.StartCounter();
            translatorHelperContent.ProcessPlugIn(true, false, false, String.Empty);
            translatorHelperContent.AddToMemo("Parse Skyrim.esm in " + TESVSnip.Functions.StopCounter() + Environment.NewLine);
            translatorHelperContent.GenerateSkyrimStringsDictionaryWithSkyrimReference();

            CloseAll();
              }
              finally
              {
            Cursor.Current = Cursors.Default;
            CloseAll();
            //translatorHelperContent.AddToMemo("Elapsed time:" + TESVSnip.Functions.StopCounter() + Environment.NewLine);
              }

              MessageBox.Show(
            "The " + translatorHelperContent.GetSourceLanguage() + " to " + translatorHelperContent.GetTargetLanguage() + " dictionary has been generated." +
            Environment.NewLine +
            "If STEAM updates STRINGS files, remember to regenerate dictionaries.",
            "Translator Helper", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
コード例 #4
0
ファイル: Spells.cs プロジェクト: rxantos/tesv-snip
        public static void SanitizePlugin(Plugin plugin)
        {
            // performance update to prevent lists from updating currently selected record
            bool oldHoldUpdates = BaseRecord.HoldUpdates;
            try
            {
                BaseRecord.HoldUpdates = true;
                if (plugin == null)
                    throw new ApplicationException("Cannot select plugin");

                var hdr = plugin.Records.OfType<Rec>().FirstOrDefault(x => x.Name == "TES4");
                if (hdr == null)
                {
                    throw new ApplicationException(Resources.PluginLacksAValidTes4RecordCannotContinue);
                }

                var toParse = new Queue<BaseRecord>(plugin.Records.OfType<BaseRecord>().Where(x => !x.Equals(hdr)));
                plugin.Clear();
                plugin.AddRecord(hdr);

                var groups = new Dictionary<string, GroupRecord>();

                foreach (string s in SanitizeOrder)
                {
                    var gr = new GroupRecord(s);
                    plugin.AddRecord(gr);
                    groups[s] = gr;
                }

                bool looseGroupsWarning = false;
                bool unknownRecordsWarning = false;
                while (toParse.Count > 0)
                {
                    var r = toParse.Dequeue();
                    if (r is GroupRecord)
                    {
                        var gr = (GroupRecord)r;
                        if (gr.ContentsType == "CELL" || gr.ContentsType == "WRLD" || gr.ContentsType == "DIAL")
                        {
                            var gr2 = groups[gr.ContentsType];
                            foreach (BaseRecord r2 in gr.Records) gr2.AddRecord(r2);
                            gr.Clear();
                        }
                        else
                        {
                            foreach (BaseRecord r2 in gr.Records) toParse.Enqueue(r2);
                            gr.Clear();
                        }
                    }
                    else if (r is Record)
                    {
                        var r2 = (Record)r;
                        if (LooseGroups.Contains(r2.Name))
                        {
                            looseGroupsWarning = true;
                            plugin.AddRecord(r2);
                        }
                        else
                        {
                            if (groups.ContainsKey(r2.Name)) 
                                groups[r2.Name].AddRecord(r2);
                            else
                            {
                                unknownRecordsWarning = true;
                                plugin.AddRecord(r2);
                            }
                        }
                    }
                }

                foreach (GroupRecord gr2 in groups.Values)
                {
                    if (gr2.Records.Count == 0) plugin.DeleteRecord(gr2);
                }
                if (looseGroupsWarning)
                {
                    MessageBox.Show(Resources.CannotSanitizeLooseGroups, Resources.WarningText);
                }
                if (unknownRecordsWarning)
                {
                    MessageBox.Show(Resources.CannotSanitizeUnknownRecords, Resources.WarningText);
                }

                plugin.InvalidateCache();

                UpdateRecordCount(plugin);

                /* int reccount = -1 + plugin.Records.Cast<Rec>().Sum(r => sanitizeCountRecords(r));
                var tes4 = plugin.Records.OfType<Record>().FirstOrDefault(x => x.Name == "TES4");
                if (tes4 != null)
                {
                    if (tes4.SubRecords.Count > 0 && tes4.SubRecords[0].Name == "HEDR" && tes4.SubRecords[0].Size >= 8)
                    {
                        byte[] data = tes4.SubRecords[0].GetData();
                        byte[] reccountbytes = TypeConverter.si2h(reccount);
                        for (int i = 0; i < 4; i++) data[4 + i] = reccountbytes[i];
                        tes4.SubRecords[0].SetData(data);
                    }
                } */
            }
            finally
            {
                BaseRecord.HoldUpdates = oldHoldUpdates;
            }
        }
コード例 #5
0
ファイル: Spells.cs プロジェクト: rxantos/tesv-snip
 internal static int InternalizeStrings(Plugin plugin)
 {
     bool anyModified = false;
     int count = 0;
     foreach (var record in plugin.Enumerate().OfType<Record>())
     {
         record.MatchRecordStructureToRecord();
         foreach (var sr in record.SubRecords)
         {
             var elements = record.EnumerateElements(sr, rawData: true).ToList();
             foreach (var elem in elements)
             {
                 if (elem.Structure != null && elem.Structure.type == ElementValueType.LString)
                 {
                     var data = elem.Data;
                     uint id = TypeConverter.h2i(data);
                     if (id == 0) continue;
                     if (data.Count == 4)
                     {
                         var str = plugin.LookupFormStrings(id);
                         if (!string.IsNullOrEmpty(str))
                         {
                             elem.AssignValue<ArraySegment<byte>>(new ArraySegment<byte>(TypeConverter.str2h(str)));
                             ++count;
                         }
                     }
                 }
             }
             if (elements.Any(x => x.Changed))
             {
                 // need to repack the structure
                 using (var ms = new MemoryStream(sr.GetReadonlyData().Length))
                 {
                     foreach (var seg in elements.Select(elem => elem.Data))
                         ms.Write(seg.Array, seg.Offset, seg.Count);
                     sr.SetData(ms.ToArray());
                 }
                 anyModified = true;
             }
         }
     }
     if (anyModified)
     {
         var tes4 = plugin.Records.OfType<Record>().FirstOrDefault(x => x.Name == "TES4");
         if (tes4 != null) tes4.Flags1 &= ~0x00000080U;
     }
     return count;
 }
コード例 #6
0
ファイル: Spells.cs プロジェクト: rxantos/tesv-snip
        internal static int CreateStringStubs(Plugin plugin)
        {
            if (plugin == null)
                return -1;

            var masters = plugin.Masters;
            if (masters == null || masters.Length == 0)
                return -1;
            int count = 0;
            foreach (var record in plugin.Enumerate().OfType<Record>())
            {
                record.MatchRecordStructureToRecord();
                foreach (var sr in record.SubRecords)
                {
                    var elements = record.EnumerateElements(sr, rawData: true).ToList();
                    foreach (var elem in elements)
                    {
                        if (elem.Structure != null && elem.Structure.type == ElementValueType.LString)
                        {
                            var data = elem.Data;
                            if (data.Count == 4)
                            {
                                string value;
                                uint id = TypeConverter.h2i(data);
                                if (id == 0) continue;
                                if (!plugin.Strings.TryGetValue(id, out value))
                                {
                                    value = string.Format("STUB: {0} {1}", record.DescriptiveName, sr.DescriptiveName);
                                    plugin.Strings[id] = value;
                                    ++count;
                                }
                            }
                        }
                    }
                }
            }
            return count;
        }
コード例 #7
0
ファイル: Spells.cs プロジェクト: rxantos/tesv-snip
        internal static int CleanUnusedStrings(Plugin plugin)
        {
            if (plugin == null)
                return -1;

            var masters = plugin.Masters;
            if (masters == null || masters.Length == 0)
                return -1;

            LocalizedStringDict oldStrings = plugin.Strings;
            plugin.Strings = new LocalizedStringDict();
            foreach (var record in plugin.Enumerate().OfType<Record>())
            {
                record.MatchRecordStructureToRecord();
                foreach (var sr in record.SubRecords)
                {
                    var elements = record.EnumerateElements(sr, rawData: true).ToList();
                    foreach (var elem in elements)
                    {
                        if (elem.Structure != null && elem.Structure.type == ElementValueType.LString)
                        {
                            var data = elem.Data;
                            if (data.Count == 4)
                            {
                                string value;
                                uint id = TypeConverter.h2i(data);
                                if (id == 0) continue;
                                if (oldStrings.TryGetValue(id, out value))
                                {
                                    oldStrings.Remove(id);
                                    plugin.Strings[id] = value;
                                }
                            }
                        }
                    }
                }
            }
            return oldStrings.Count;
        }
コード例 #8
0
ファイル: Spells.cs プロジェクト: rxantos/tesv-snip
        /// <summary>
        /// Extract any internalized strings and put in string table
        /// </summary>
        /// <param name="plugin"></param>
        public static int ExtractInternalStrings(Plugin plugin)
        {
            int count = 0;
            // uint maxid = plugin.Masters.Max(x=>x.Strings.Count > 0 ? x.Strings.Keys.Max() : 0); // No need to check the masters string since the numbers are unique for every plugin

            bool anyModified = false;
            foreach (var record in plugin.Enumerate().OfType<Record>())
            {
                record.MatchRecordStructureToRecord();
                foreach (var sr in record.SubRecords)
                {
                    var elements = record.EnumerateElements(sr, rawData: true).ToList();
                    foreach (var elem in elements)
                    {
                        if (elem.Structure != null && elem.Structure.type == ElementValueType.LString)
                        {
                            var data = elem.Data;
                            uint id = TypeConverter.h2i(data);
                            if (id == 0) continue;
                            if (data.Count == 4 && TypeConverter.IsLikelyString(data))
                            {
                                string str;
                                if (plugin.Strings.TryGetValue(id, out str))
                                    continue;
                            }
                            if (data.Count != 4 || TypeConverter.IsLikelyString(data))
                            {
                                string value = TypeConverter.GetString(data);
                                if (!String.IsNullOrEmpty(value))
                                {
                                    // uint nextid = Math.Max(maxid, plugin.Strings.Count == 0 ? 0 : plugin.Strings.Keys.Max()) + 1; // No need to check the masters strings since the numbers are unique for every plugin
                                    uint nextid = (plugin.Strings.Count == 0 ? 0 : plugin.Strings.Keys.Max()) + 1;
                                    int idx = plugin.Strings.FindValue(value);
                                    if (idx >= 0)
                                    {
                                        nextid = plugin.Strings.ElementAt(idx).Key;
                                    }
                                    else
                                    {
                                        plugin.Strings[nextid] = value;                                        
                                    }
                                    elem.AssignValue<ArraySegment<byte>>(
                                        new ArraySegment<byte>((byte[])TypeConverter.i2h(nextid).Clone()));
                                    ++count;
                                }
                            }
                        }
                    }
                    if (elements.Any(x => x.Changed))
                    {
                        // need to repack the structure
                        using (var ms = new MemoryStream(sr.GetReadonlyData().Length))
                        {
                            foreach (var seg in elements.Select(elem => elem.Data))
                                ms.Write(seg.Array, seg.Offset, seg.Count);
                            sr.SetData(ms.ToArray());
                        }
                        anyModified = true;
                    }
                }
            }
            if (anyModified)
            {
                var tes4 = plugin.Records.OfType<Record>().FirstOrDefault(x => x.Name == "TES4");
                if (tes4 != null) tes4.Flags1 |= 0x00000080U;
            }
            return count;
        }
コード例 #9
0
ファイル: Spells.cs プロジェクト: rxantos/tesv-snip
        /// <summary>
        /// Copy any strings references from master not currently in current plugin
        /// </summary>
        /// <param name="plugin"></param>
        internal static int CopyMasterStringReferences(Plugin plugin)
        {
            if (plugin == null)
                return -1;

            var masters = plugin.Masters;
            if (masters == null || masters.Length == 0)
                return -1;
            int count = 0;

            foreach (var record in plugin.Enumerate().OfType<Record>())
            {
                record.MatchRecordStructureToRecord();
                foreach (var sr in record.SubRecords)
                {
                    var elements = record.EnumerateElements(sr, rawData: true).ToList();
                    foreach (var elem in elements)
                    {
                        if (elem.Structure != null && elem.Structure.type == ElementValueType.LString)
                        {
                            var data = elem.Data;
                            if (data.Count == 4)
                            {
                                string value;
                                uint id = TypeConverter.h2i(data);
                                if (id == 0) continue;
                                if (!plugin.Strings.TryGetValue(id, out value))
                                {
                                    foreach (var master in masters.Reverse())
                                    {
                                        if ( master.Strings.TryGetValue(id, out value) )
                                        {
                                            ++count;
                                            plugin.Strings[id] = value;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return count;
        }
コード例 #10
0
ファイル: Spells.cs プロジェクト: rxantos/tesv-snip
 public static void updateFormIDReference(Plugin plugin, uint oldFormID, uint newFormID, ref uint refCount)
 {
     foreach (Record record in plugin.Enumerate().OfType<Record>())
     {
         record.MatchRecordStructureToRecord();
         foreach (SubRecord sr in record.SubRecords)
         {
             var elements =  sr.EnumerateElements(true).ToList();
             foreach (Element e in elements)
             {
                 if (e.Structure != null && e.Structure.type == ElementValueType.FormID)
                 {
                     if ((uint)e.Value == oldFormID)
                     {
                         e.AssignValue<uint>((object)newFormID);
                         refCount++;
                     }
                 }
             }
         }
     }
 }
コード例 #11
0
ファイル: Spells.cs プロジェクト: rxantos/tesv-snip
 public static void updateFormIDReference(Plugin plugin, uint oldFormID, uint newFormID)
 {
     uint refCount = 0;
     updateFormIDReference(plugin, oldFormID, newFormID, ref refCount);
 }
コード例 #12
0
ファイル: Spells.cs プロジェクト: rxantos/tesv-snip
 public static uint getNextFormID(Plugin plugin)
 {
     var tes4 = plugin.Records.OfType<Record>().FirstOrDefault(x => x.Name == "TES4");
     if (tes4 != null && tes4.SubRecords.Count > 0 && tes4.SubRecords[0].Name == "HEDR" && tes4.SubRecords[0].Size >= 8)
     {
         byte[] data = tes4.SubRecords[0].GetData();
         uint formid = (uint)TypeConverter.GetObject<uint>(data, 8);
         TypeConverter.i2h(formid + 1, data, 8);
         tes4.SubRecords[0].SetData(data);
         return formid;
     }
     throw new ApplicationException(Resources.PluginLacksAValidTes4RecordCannotContinue);
 }
コード例 #13
0
ファイル: Spells.cs プロジェクト: rxantos/tesv-snip
 public static void StripEDIDs(Plugin p)
 {
     foreach (Rec r in p.Records) StripEDIDsInternal(r);
 }
コード例 #14
0
ファイル: ScriptCompiler.cs プロジェクト: rxantos/tesv-snip
        public static void Setup(Plugin[] plugins)
        {
            if (!Inited) Init();
            TokenStream.Reset();
            edidList.Clear();
            globals.Clear();
            farVars.Clear();
            var records = new Dictionary<uint, Record>();
            uint mask;
            var quests = new List<Pair<uint, Record>>();
            var refs = new List<Pair<uint, Record>>();
            var RefLookupTable = new Dictionary<uint, uint>();
            for (uint i = 0; i < plugins.Length - 1; i++)
            {
                var plugin = plugins[i];
                if (plugin == null) continue;
                if (plugin.Records.OfType<BaseRecord>().FirstOrDefault(x => x.Name == "TES4") == null) continue;

                mask = (uint) plugin.Masters.Count();
                mask <<= 24;
                uint id = i << 24;
                foreach (Rec r in plugin.Records) RecursePlugin(r, mask, id, records, quests, refs);

                foreach (Pair<uint, Record> recs in refs)
                {
                    if (RefLookupTable.ContainsKey(recs.Key) && RefLookupTable[recs.Key] != 0)
                        quests.Add(new Pair<uint, Record>(RefLookupTable[recs.Key], recs.Value));
                    else if (records.ContainsKey(recs.Key))
                    {
                        Record r = records[recs.Key];
                        uint formID = 0;
                        foreach (SubRecord sr in r.SubRecords)
                        {
                            if (sr.Name == "SCRI")
                            {
                                byte[] bytes = sr.GetReadonlyData();
                                uint formid = (TypeConverter.h2i(bytes[0], bytes[1], bytes[2], bytes[3]));
                                if ((formid & 0xff000000) == mask)
                                {
                                    formID = (formid & 0xffffff) + id;
                                    break;
                                }
                            }
                        }
                        quests.Add(new Pair<uint, Record>(formID, recs.Value));
                    }
                }
                RefLookupTable.Clear();
            }
            foreach (Rec r in plugins[plugins.Length - 1].Records) RecursePlugin(r, records, quests, refs);
            foreach (Pair<uint, Record> recs in refs)
            {
                if (RefLookupTable.ContainsKey(recs.Key) && RefLookupTable[recs.Key] != 0)
                    quests.Add(new Pair<uint, Record>(RefLookupTable[recs.Key], recs.Value));
                else if (records.ContainsKey(recs.Key))
                {
                    Record r = records[recs.Key];
                    uint formID = 0;
                    foreach (SubRecord sr in r.SubRecords)
                    {
                        if (sr.Name == "SCRI")
                        {
                            byte[] bytes = sr.GetReadonlyData();
                            formID = (TypeConverter.h2i(bytes[0], bytes[1], bytes[2], bytes[3]));
                            break;
                        }
                    }
                    quests.Add(new Pair<uint, Record>(formID, recs.Value));
                }
            }

            foreach (KeyValuePair<uint, Record> recs in records)
            {
                string edid = recs.Value.SubRecords[0].GetStrData().ToLowerInvariant();
                if (recs.Value.Name == "GLOB")
                {
                    TokenStream.AddGlobal(edid);
                    globals[edid] = recs.Key;
                }
                else
                {
                    TokenStream.AddEdid(edid);
                    edidList[edid] = new Pair<uint, string>(recs.Key, recs.Value.Name);
                }
            }
            edidList["player"] = new Pair<uint, string>(0x14, "NPC_");
            TokenStream.AddEdid("player");
            edidList["playerref"] = new Pair<uint, string>(0x14, "NPC_");
            TokenStream.AddEdid("playerref");

            var vars = new Dictionary<string, ushort>();
            foreach (Pair<uint, Record> quest in quests)
            {
                if (!records.ContainsKey(quest.Key)) continue;
                Record scpt = records[quest.Key];
                string edid = quest.Value.SubRecords[0].GetStrData();
                for (int i = 0; i < scpt.SubRecords.Count - 1; i++)
                {
                    if (scpt.SubRecords[i].Name == "SLSD")
                    {
                        byte[] bytes = scpt.SubRecords[i].GetReadonlyData();
                        vars[scpt.SubRecords[i + 1].GetStrData().ToLowerInvariant()] = TypeConverter.h2s(bytes[0],
                                                                                                         bytes[1]);
                    }
                }
                if (vars.Count > 0)
                {
                    farVars[edid.ToLowerInvariant()] = vars;
                    vars = new Dictionary<string, ushort>();
                }
            }
        }