private static string GetPath(string directory, string scriptNamePrefix, TES4Record record, bool includeFormID, StageIndexAndLogIndex?stageIndexAndLogIndex)
        {
            string fileNameNoExt = BuildTargetsWriter.GetFileNameNoExt(scriptNamePrefix, record, includeFormID, stageIndexAndLogIndex);
            string path          = directory + fileNameNoExt + ".txt";

            return(path);
        }
        public static StageMap BuildStageMap(TES4Record qust)
        {
            string contentsString     = BuildString(qust);
            var    stageMapDictionary = StageMapDictionaryBuilder.Build(contentsString.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries));

            return(new StageMap(stageMapDictionary, false));
        }
        private static string FixScriptName(TES4Record record, string contents)
        {
            string scriptEditorID        = record.GetEditorID();
            Regex  soughtScriptName      = new Regex("((S|s)cript(N|n)ame|scn)( +|\t)([A-Za-z0-9_]+)( |\t)?(\r\n|$)");
            Match  soughtScriptNameMatch = soughtScriptName.Match(contents);

            if (!soughtScriptNameMatch.Success)
            {
                throw new InvalidOperationException("Script name not found in script for " + scriptEditorID + ".");
            }
            Group editorIDGroup = soughtScriptNameMatch.Groups[5];

            if (editorIDGroup.Value != scriptEditorID)
            {
                if (scriptEditorID.Equals(editorIDGroup.Value.Replace("_", ""), StringComparison.OrdinalIgnoreCase))
                {
                    contents = contents.Substring(0, editorIDGroup.Index) + scriptEditorID + contents.Substring(editorIDGroup.Index + editorIDGroup.Length);
                }
                else
                {
                    throw new InvalidOperationException("Script name was invalid but couldn't be replaced.  Expected script name:  " + scriptEditorID + ".");
                }
            }
            return(contents);
        }
Example #4
0
 public static CELLRecord From(SSEPlugin.Record record, TES4Record plugin)
 {
     return(new CELLRecord()
     {
         edid = record.GetFirstField("EDID", ZString.From),
         full = record.GetFirstField("FULL", v => LString.From(v, plugin))
     });
 }
Example #5
0
        public static string GetFileNameNoExt(string prefix, TES4Record record, bool includeFormID, StageIndexAndLogIndex?stageIndexAndLogIndex)
        {
            string?editorID            = record.TryGetEditorID();
            string editorID_formID     = (editorID != null ? editorID : "").ToLower() + (includeFormID ? "_" + (record.FormID + 0x01000000).ToString("x").PadLeft(8, '0') : "");
            string indexPlusFileNumber = stageIndexAndLogIndex != null ? "_" + stageIndexAndLogIndex.StageIndex.ToString() + "_" + stageIndexAndLogIndex.LogIndex.ToString() : "";

            return(prefix + editorID_formID + indexPlusFileNumber);
        }
        public static void GenerateINFOAddTopicScripts(ESMAnalyzer esmAnalyzer, BuildTracker buildTracker, IBuildTarget tifBuildTarget)
        {
            TES5TypeInferencer    typeInferencer    = new TES5TypeInferencer(esmAnalyzer);
            TES5ObjectCallFactory objectCallFactory = new TES5ObjectCallFactory(typeInferencer);
            TES4TopicsToTES5GlobalVariableFinder globalVariableFinder = new TES4TopicsToTES5GlobalVariableFinder();
            TES5GlobalVariables globalVariables = esmAnalyzer.GlobalVariables;
            var builtTIFs = buildTracker.GetBuiltScripts(BuildTargetFactory.TIFName);

            foreach (TES4Record infoRecord in esmAnalyzer.GetRecords().Where(r => r.RecordType == TES4RecordType.INFO))
            {
                TES4SubrecordData[] names = infoRecord.GetSubrecords("NAME").ToArray();
                if (names.Any())
                {
                    string                fragment0Name     = TES5FragmentFactory.GetFragmentName(0);
                    string                nameTES5FormIDHex = (infoRecord.FormID + 0x01000000).ToString("x8");
                    string                scriptName        = TES5ReferenceFactory.tif_Prefix + "_" + nameTES5FormIDHex;
                    TES5Script?           infoTIF           = builtTIFs.Where(s => s.Key == scriptName).Select(s => s.Value.Script).FirstOrDefault();
                    TES5FunctionCodeBlock fragment0;
                    if (infoTIF != null)
                    {
                        fragment0 = infoTIF.BlockList.Blocks.OfType <TES5FunctionCodeBlock>().Where(b => b.BlockName == fragment0Name).First();
                    }
                    else
                    {
                        TES5ScriptHeader  scriptHeader  = TES5ScriptHeaderFactory.GetFromCacheOrConstructByBasicType(scriptName, TES5BasicType.T_TOPICINFO, TES5TypeFactory.TES4_Prefix, true);
                        TES5GlobalScope   globalScope   = new TES5GlobalScope(scriptHeader);
                        TES5FunctionScope functionScope = new TES5FunctionScope(fragment0Name);
                        functionScope.AddParameter(new TES5SignatureParameter("akSpeakerRef", TES5BasicType.T_OBJECTREFERENCE, true));
                        TES5LocalScope localScope = new TES5LocalScope(functionScope);
                        TES5CodeScope  codeScope  = TES5CodeScopeFactory.CreateCodeScope(localScope);
                        fragment0 = new TES5FunctionCodeBlock(functionScope, codeScope, TES5VoidType.Instance, false, true);
                        TES5BlockList blockList = new TES5BlockList()
                        {
                            fragment0
                        };
                        infoTIF = new TES5Script(globalScope, blockList, true);
                        string     outputPath = tifBuildTarget.GetTranspileToPath(scriptName);
                        TES5Target target     = new TES5Target(infoTIF, outputPath);
                        buildTracker.RegisterBuiltScript(tifBuildTarget, target);
                    }
                    foreach (TES4SubrecordData name in names)
                    {
                        int                 formID                   = infoRecord.ExpandBytesIntoFormID(name);
                        TES4Record          addedTopic               = esmAnalyzer.GetRecordByFormID(formID);
                        Tuple <int, string>?globalVariable           = globalVariableFinder.GetGlobalVariableNullable(addedTopic.FormID);
                        string              globalVariableEditorID   = globalVariable != null ? globalVariable.Item2 : globalVariableFinder.GetGlobalVariableEditorID(addedTopic.GetEditorID());
                        Nullable <int>      globalVariableTES5FormID = globalVariable != null ? globalVariable.Item1 : (Nullable <int>)null;
                        TES5Property        topicAddedProperty       = TES5PropertyFactory.ConstructWithTES5FormID(globalVariableEditorID, TES5BasicType.T_GLOBALVARIABLE, globalVariableEditorID, globalVariableTES5FormID);
                        infoTIF.GlobalScope.AddPropertyIfNotExists(topicAddedProperty);
                        TES5Reference topicAddedReference = TES5ReferenceFactory.CreateReferenceToVariableOrProperty(topicAddedProperty);
                        fragment0.AddChunk(objectCallFactory.CreateObjectCall(topicAddedReference, "SetValueInt", new TES5ObjectCallArguments()
                        {
                            new TES5Integer(1)
                        }));
                    }
                }
            }
        }
        public IEnumerable <KeyValuePair <string, KeyValuePair <int, TES5BasicType> > > GetTypesFromSCROEnumerable(TES4Record scriptTES4Record, StageIndexAndLogIndex?stageIndexAndLogIndex)
        {
            TES4SubrecordData[] scroRecords  = scriptTES4Record.GetSCRORecords(stageIndexAndLogIndex).ToArray();
            HashSet <int>       foundFormIDs = new HashSet <int>();

            return(scroRecords
                   .Select(r => r.FirstFourBytesToInt())
                   .Where(formID => !foundFormIDs.Contains(formID))
                   .Select(formID =>
            {
                foundFormIDs.Add(formID);
                string edid;
                TES5BasicType tes5Type;
                if (formID == TES5PlayerReference.FormID)
                {
                    edid = TES5PlayerReference.PlayerRefName;
                    tes5Type = TES5PlayerReference.TES5TypeStatic;
                }
                else
                {
                    TES4Record record = GetRecordByFormID(formID);
                    edid = record.GetSubrecord("EDID").ToStringTrim();

                    /*
                     * if (record.RecordType == TES4RecordType.CREA || record.RecordType == TES4RecordType.NPC_)
                     * {
                     *  //These probably just need to be ActorBase, but that doesn't work in all situations.
                     *  List<int>? formIDsFromName = TryGetFormIDsByName(formID);
                     *  if (formIDsFromName == null || formIDsFromName.Count != 1)
                     *  {//If no form IDs were found or if not exactly one form ID was found, refer to the ActorBase.
                     *      tes5Type = TES5BasicType.T_ACTORBASE;
                     *  }
                     *  else
                     *  {//If exactly one form ID was found, refer to the Actor;
                     *      if (formIDsFromName != null) { formIDs = formIDsFromName; }
                     *      tes5Type = TES5BasicType.T_ACTOR;
                     *  }
                     *  tes5Type = TES5BasicType.T_ACTORBASE;
                     * }
                     * else
                     * {
                     *  tes5Type = TypeMapper.GetTES5BasicType(record.RecordType, out _);
                     * }
                     */
                    tes5Type = TypeMapper.GetTES5BasicType(record.RecordType);
                    //It seems Oblivion.esm's scroll BOOK records are now SCRL records in Skyblivion.esm with the same form ID.
                    if (tes5Type == TES5BasicType.T_BOOK && edid.IndexOf("scroll", StringComparison.OrdinalIgnoreCase) != -1 &&
                        !(edid == "MG05FingersScroll" || edid == "TG11ElderScroll" || edid == "TG04ElderScrollsHistory") /*These actually are BOOKs.*/)
                    {
                        tes5Type = TES5BasicType.T_SCROLL;
                    }
                }
                return new KeyValuePair <string, KeyValuePair <int, TES5BasicType> >(edid, new KeyValuePair <int, TES5BasicType>(formID, tes5Type));
            }));
        }
        private static void Write(string directory, string scriptNamePrefix, TES4Record record, bool includeFormID, StageIndexAndLogIndex?stageIndexAndLogIndex, bool allowFixScriptName, string contents)
        {
            string path = GetPath(directory, scriptNamePrefix, record, includeFormID, stageIndexAndLogIndex);

            if (allowFixScriptName)
            {
                contents = FixScriptName(record, contents);
            }
            contents += scriptNamePrefix != "" ? "\r\n" : "";//only for non-Standalone; allows compilation to complete
            FileWriter.WriteAllTextOrThrowIfExists(path, contents);
        }
Example #9
0
        public static void Write(string sourcePath, TES4Record qust)
        {
            string[] aliases         = ESMAnalyzer.GetReferenceAliases(qust).ToArray();
            string   fileNameNoExt   = BuildTargetsWriter.GetFileNameNoExt(TES5ReferenceFactory.qf_Prefix, qust, true, null);
            string   aliasesPath     = sourcePath + fileNameNoExt + ".aliases";
            string   aliasesContents = string.Join("\r\n", aliases)
#if !NEWBT
                                       + "\r\n"
#endif
            ;

            FileWriter.WriteAllTextOrThrowIfExists(aliasesPath, aliasesContents);
        }
Example #10
0
        public TES4Master(string filename)
        {
            var gameID = GameID.Oblivion;

            switch (Path.GetFileNameWithoutExtension(filename).ToLower())
            {
            case "oblivion": gameID = GameID.Oblivion; break;

            case "skyrim": gameID = GameID.Skyrim; break;

            case "fallout3": gameID = GameID.Fallout3; break;

            case "falloutNV": gameID = GameID.FalloutNV; break;

            case "fallout4": gameID = GameID.Fallout4; break;
            }

            _groups = new Dictionary <string, Group>();

            using (var reader = new BetterBinaryReader(File.OpenRead(filename)))
            {
                var tes4 = new TES4Record();
                tes4.Deserialize(reader, reader.ReadString(4), gameID);

                if (tes4.Type != "TES4")
                {
                    throw new Exception("That's not a TES4/5 compatible master file.");
                }

                Utils.LogBuffer("# Loading {0}", gameID);
                Utils.LogBuffer("\t- Record: {0}", tes4.Type);

                string groupName = string.Empty;
                Group  group     = null;

                while (reader.Position < reader.Length)
                {
                    groupName = reader.ReadString(4);
                    group     = new Group();
                    group.Deserialize(reader, groupName, gameID);

                    if (_groups.ContainsKey(group.Label))
                    {
                        continue;
                    }

                    _groups.Add(group.Label, group);
                }
            }
        }
        private Nullable <KeyValuePair <int, TES5BasicType> > GetTypeFromSCRO(TES4Record scriptTES4Record, StageIndexAndLogIndex?stageIndexAndLogIndex, string propertyName, bool throwException)
        {
            var types = GetTypesFromSCRO(scriptTES4Record, stageIndexAndLogIndex);
            KeyValuePair <int, TES5BasicType> type;

            if (types.TryGetValue(propertyName, out type))
            {
                return(type);
            }
            if (throwException)
            {
                throw new ConversionException("Form " + scriptTES4Record.TryGetEditorID() + " (" + scriptTES4Record.FormID.ToString() + ")" + (stageIndexAndLogIndex != null ? ", " + stageIndexAndLogIndex.ToString() : "") + " did not have a property named " + propertyName + ".");
            }
            return(null);
        }
        public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope)
        {
            TES4FunctionArguments functionArguments = function.Arguments;
            ITES4StringValue      apiToken          = functionArguments[0];
            string       cellEditorID = apiToken.StringValue;
            string       locationPropertyNameWithoutSuffix = cellEditorID + "Location";
            string       locationPropertyNameWithSuffix    = TES5Property.AddPropertyNameSuffix(locationPropertyNameWithoutSuffix);
            TES5Property?locationProperty = globalScope.TryGetPropertyByName(locationPropertyNameWithSuffix);

            if (locationProperty == null)
            {
                int tes5LocationFormID;
                if (cellToLocationFinder.TryGetLocationFormID(cellEditorID, out tes5LocationFormID))
                {
                    locationProperty = TES5PropertyFactory.ConstructWithTES5FormID(locationPropertyNameWithoutSuffix, TES5BasicType.T_LOCATION, null, tes5LocationFormID);
                    globalScope.AddProperty(locationProperty);
                }
                else
                {
                    TES5ObjectCall getParentCell      = this.objectCallFactory.CreateObjectCall(calledOn, "GetParentCell");
                    TES5ObjectCall getParentCellName  = this.objectCallFactory.CreateObjectCall(getParentCell, "GetName");
                    TES4Record     cellRecord         = this.esmAnalyzer.GetRecordByEDIDInTES4Collection(cellEditorID);
                    string?        cellNameWithSpaces = cellRecord.TryGetSubrecordTrim("FULL");
                    if (cellNameWithSpaces == null || cellNameWithSpaces.IndexOf("Dummy", StringComparison.OrdinalIgnoreCase) != -1)
                    {
                        cellNameWithSpaces = cellEditorID;
                    }
                    TES5String cellNameTES5String         = new TES5String(cellNameWithSpaces);
                    TES5ObjectCallArguments findArguments = new TES5ObjectCallArguments()
                    {
                        getParentCellName,
                        cellNameTES5String
                    };
                    TES5ObjectCall substring = this.objectCallFactory.CreateObjectCall(TES5StaticReferenceFactory.StringUtil, "Find", findArguments);
                    return(TES5ExpressionFactory.CreateComparisonExpression(substring, TES5ComparisonExpressionOperator.OPERATOR_EQUAL, new TES5Integer(0)));
                }
            }
            TES5Reference locationReference = TES5ReferenceFactory.CreateReferenceToVariableOrProperty(locationProperty);

            return(this.objectCallFactory.CreateObjectCall(calledOn, "IsInLocation", new TES5ObjectCallArguments()
            {
                locationReference
            }));
        }
        /*
         * @todo REFACTOR, it"s really ugly!
         * @throws ConversionException
         */
        public ITES5Type GetScriptTypeByEDID(string edid)
        {
            string    edidLower = edid.ToLower();
            ITES5Type?value;

            if (this.edidLowerCache.TryGetValue(edidLower, out value))
            {
                return(value);
            }
            TES4Record attachedNameRecord = GetRecordByEDIDAndFollowNAME(edid);

            Nullable <int> scriptFormid = attachedNameRecord.TryGetSubrecordAsFormID("SCRI");

            if (scriptFormid == null)
            {
                throw new ConversionException("Cannot resolve script type for " + edid + " - Asked base record has no script bound.");
            }

            string           scriptRecordEDID = GetEDIDByFormID(scriptFormid.Value);
            TES5ScriptHeader scriptHeader     = TES5ScriptHeaderFactory.GetFromCacheOrConstructByBasicType(scriptRecordEDID, TypeMapper.GetTES5BasicType(attachedNameRecord.RecordType), TES5TypeFactory.TES4Prefix, false);

            this.edidLowerCache.Add(edidLower, scriptHeader.ScriptType);
            return(scriptHeader.ScriptType);
        }
        public Nullable <KeyValuePair <int, TES5BasicType> > GetTypeFromSCRO(string scriptEDID, string propertyName)
        {
            TES4Record scriptTES4Record = GetRecordByEDIDInTES4Collection(scriptEDID);

            return(GetTypeFromSCRO(scriptTES4Record, null, propertyName, !(scriptTES4Record.FormID == 211721 && propertyName == "test")));//WTM:  Note:  Special Case:  property not found in SCRO records
        }
        public static string BuildString(TES4Record qust)
        {
            const string   indx = "INDX", qsta = "QSTA", ctda = "CTDA";
            var            subrecords     = qust.GetSubrecords(new string[] { indx, qsta, ctda });
            Nullable <int> targetIndex    = null;
            int            maxTargetIndex = 0;
            List <int>     stageIndexes   = new List <int>();
            Dictionary <int, List <Tuple <Func <int, bool>, bool> > > targetFuncs = new Dictionary <int, List <Tuple <Func <int, bool>, bool> > >();

            foreach (var subrecord in subrecords)
            {
                if (subrecord.Key == indx)
                {
                    int stageIndex = (int)subrecord.Value.FirstByte();
                    stageIndexes.Add(stageIndex);
                    targetIndex = null;
                }
                else if (subrecord.Key == qsta)
                {
                    targetIndex = targetIndex == null ? 0 : targetIndex.Value + 1;
                    if (targetIndex.Value > maxTargetIndex)
                    {
                        maxTargetIndex = targetIndex.Value;
                    }
                }
                else if (subrecord.Key == ctda)
                {
                    if (targetIndex == null)
                    {
                        continue;
                    }
                    int targetIndexInt = targetIndex.Value;
                    IReadOnlyList <byte> bytes = subrecord.Value.Bytes;
                    int  functionIndex = BitConverter.ToInt32(bytes.Skip(8).Take(4).ToArray(), 0);
                    bool getStage = functionIndex == 58, getStageDone = functionIndex == 59;
                    if (getStage)
                    {
                        bool anyRemainingNonZero = bytes.Skip(16).Where(b => b != (byte)0).Any();
                        if (anyRemainingNonZero)
                        {
                            throw new InvalidOperationException("anyRemainingNonZero");
                        }
                        int formID1 = BitConverter.ToInt32(bytes.Skip(12).Take(4).ToArray(), 0);
                        //int formID2 = BitConverter.ToInt32(bytes.Skip(16).Take(4).ToArray(), 0);
                        if (qust.FormID != formID1)
                        {
                            continue;
                        }
                        byte firstByte = bytes[0];
                        int  compareOperator = firstByte & 0b11110000;
                        int  flags = firstByte & 0b00001111;
                        bool equalTo = compareOperator == 0, notEqualTo = compareOperator == 0b00100000, lessThan = compareOperator == 0b10000000, greaterThan = compareOperator == 0b01000000, greaterThanOrEqualTo = compareOperator == 0b01100000, lessThanOrEqualTo = compareOperator == 0b10100000;
                        if (!(equalTo || notEqualTo || lessThan || greaterThan || greaterThanOrEqualTo || lessThanOrEqualTo))
                        {
                            throw new InvalidOperationException("Invalid compareOperator");
                        }
                        bool flagsNone = flags == 0, flagsOr = flags == 1;
                        if (!(flagsNone || flagsOr))
                        {
                            throw new InvalidOperationException("Invalid flags");
                        }
                        var currentList = targetFuncs.GetOrAdd(targetIndexInt, () => new List <Tuple <Func <int, bool>, bool> >(new List <Tuple <Func <int, bool>, bool> >()));
                        Func <int, bool> newFunc;
                        float            comparisonValue = BitConverter.ToSingle(bytes.Skip(4).Take(4).ToArray(), 0);//stage
                        if (equalTo)
                        {
                            newFunc = stageID => stageID == comparisonValue;
                        }
                        else if (notEqualTo)
                        {
                            newFunc = stageID => stageID != comparisonValue;
                        }
                        else if (lessThan)
                        {
                            newFunc = stageID => stageID < comparisonValue;
                        }
                        else if (lessThanOrEqualTo)
                        {
                            newFunc = stageID => stageID <= comparisonValue;
                        }
                        else if (greaterThan)
                        {
                            newFunc = stageID => stageID > comparisonValue;
                        }
                        else if (greaterThanOrEqualTo)
                        {
                            newFunc = stageID => stageID >= comparisonValue;
                        }
                        else
                        {
                            throw new InvalidOperationException();
                        }
                        currentList.Add(new Tuple <Func <int, bool>, bool>(newFunc, flagsOr));
                    }
                    else if (getStageDone)
                    {
                        bool anyRemainingNonZero = bytes.Skip(20).Where(b => b != (byte)0).Any();
                        if (anyRemainingNonZero)
                        {
                            throw new InvalidOperationException("anyRemainingNonZero");
                        }
                        int formID1 = BitConverter.ToInt32(bytes.Skip(12).Take(4).ToArray(), 0);
                        int formID2 = BitConverter.ToInt32(bytes.Skip(16).Take(4).ToArray(), 0);
                        if (qust.FormID != formID1)
                        {
                            continue;
                        }
                        byte firstByte       = bytes[0];
                        int  compareOperator = firstByte & 0b11110000;
                        int  flags           = firstByte & 0b00001111;
                        if (!(compareOperator == 0))
                        {
                            throw new InvalidOperationException("Invalid compareOperator");
                        }
                        if (!(flags == 0 /*none*/ || flags == 1 /*or*/))
                        {
                            throw new InvalidOperationException("Invalid flags");
                        }
                        float comparisonValue = BitConverter.ToSingle(bytes.Skip(4).Take(4).ToArray(), 0);//is "done"

                        /*if (comparisonValue == 1) { targetFuncs.GetOrAddNewIfNotContainsKey(targetIndexInt).Add(stageID => stageID > comparisonValue); }
                         * else if (comparisonValue == 0) { targetFuncs.GetOrAddNewIfNotContainsKey(targetIndexInt).Add(stageID => stageID <= comparisonValue); }*/
                    }
                }
            }
            var simplifiedTargetFuncs = targetFuncs.ToDictionary(kvp => kvp.Key, kvp =>
            {
                List <Tuple <Func <int, bool>, bool> > currentList = kvp.Value;
                List <Func <int, bool> > reducedList = new List <Func <int, bool> >();
                for (int j = 0; j < currentList.Count; j++)
                {
                    var currentTuple = currentList[j];
                    if (currentTuple.Item2 || j + 1 >= currentList.Count)
                    {
                        reducedList.Add(currentTuple.Item1);
                    }
                    else
                    {
                        var nextTuple            = currentList[j + 1];
                        Func <int, bool> newFunc = si => currentTuple.Item1(si) && nextTuple.Item1(si);
                        bool or        = nextTuple.Item2;
                        currentList[j] = Tuple.Create(newFunc, or);
                        currentList.RemoveAt(j + 1);
                        j--;
                    }
                }
                return(currentList.Select(x => x.Item1).ToArray());
            });
            Dictionary <int, Dictionary <int, bool> > stageDictionary = stageIndexes.ToDictionary(stageIndex => stageIndex, stageIndex =>
            {
                Dictionary <int, bool> innerDictionary = new Dictionary <int, bool>();
                for (int i = 0; i <= maxTargetIndex; i++)
                {
                    Func <int, bool>[] currentList;
                    bool result;
                    if (!simplifiedTargetFuncs.TryGetValue(i, out currentList))
                    {
                        result = true;
                    }
                    else
                    {
                        result = currentList.Any(x => x(stageIndex));
                    }
                    innerDictionary[i] = result;
                }
                return(innerDictionary);
            });
            StringBuilder contents   = new StringBuilder();
            bool          anyTargets = targetIndex != null;

            foreach (var stage in stageDictionary.OrderBy(s => s.Key))
            {
                var rowDictionary = stage.Value;
                contents.Append(stage.Key).Append(" - ");
                if (anyTargets)
                {
                    for (int i = 0; i <= maxTargetIndex; i++)
                    {
                        bool cell;
                        contents.Append(rowDictionary.TryGetValue(i, out cell) && cell ? "1" : "0").Append(" ");
                    }
                }
                contents.AppendLine();
            }
            return(contents.ToString());
        }
        private static void Write(TES4Collection collection, string buildTargetsPath, string scriptFolderName, string scriptNamePrefix, bool includeFormID, StageIndexAndLogIndex?stageIndexAndLogIndex, bool allowFixScriptName, TES4RecordType recordType)
        {
            Write(collection, buildTargetsPath, scriptFolderName, recordType, (record, directory) =>
            {
                string[] sctxs = record.GetSubrecordsStrings("SCTX").ToArray();
                if (sctxs.Any())
                {
                    if (sctxs.Length > 1)
                    {
                        throw new InvalidOperationException(nameof(sctxs) + ".Length > 1");
                    }
#if !NEWBT
                    if (recordType == TES4RecordType.SCPT && !ShouldWriteScript(record.GetEditorID()))
                    {
                        return;
                    }
#endif
                    Write(directory, scriptNamePrefix, record, includeFormID, stageIndexAndLogIndex, allowFixScriptName, TES4Record.ReplaceSCTXSpecialCharacters(sctxs[0]));
                }
            });
        }
 public Dictionary <string, KeyValuePair <int, TES5BasicType> > GetTypesFromSCRO(TES4Record scriptTES4Record, StageIndexAndLogIndex?stageIndexAndLogIndex)
 {
     return(GetTypesFromSCROEnumerable(scriptTES4Record, stageIndexAndLogIndex).ToDictionary(kvp => kvp.Key, kvp => kvp.Value,
                                                                                             StringComparer.OrdinalIgnoreCase//WTM:  Note:  required since cases aren't consistent (e.g., MS40HalLiurzCourtyardMark vs. MS40HalliurzCourtyardMark--notice second L)
                                                                                             ));
 }
        private static IEnumerable <string> GetReferenceAliases(ESMAnalyzer esmAnalyzer, int tes4FormID)
        {
            TES4Record qust = esmAnalyzer.GetRecordByFormID(tes4FormID);

            return(ESMAnalyzer.GetReferenceAliases(qust));
        }
        public static IEnumerable <string> GetReferenceAliases(TES4Record qust)
        {
            IEnumerable <TES4SubrecordData> qstas = qust.GetSubrecords("QSTA");

            return(qstas.Select(qsta => qust.ExpandBytesIntoFormID(qsta)).Distinct().Select(formID => "Alias_" + formID.ToString("X8")));
        }
        public Dictionary <string, KeyValuePair <int, TES5BasicType> > GetTypesFromSCRO(int scriptTES4FormID, StageIndexAndLogIndex?stageIndexAndLogIndex)
        {
            TES4Record scriptTES4Record = GetRecordByFormID(scriptTES4FormID);

            return(GetTypesFromSCRO(scriptTES4Record, stageIndexAndLogIndex));
        }
        private static void Write(IBuildTarget qfBuildTarget, IBuildTarget tifBuildTarget, TES4Record record, StageIndexAndLogIndex?stageIndexAndLogIndex, IReadOnlyList <string> aliases)
        {
            if (!aliases.Any())
            {
                return;
            }
#if !NEWBT
            bool playerRefFound = false;
            aliases = aliases.Where(a =>
            {
                if (a == TES5PlayerReference.PlayerRefName)
                {
                    playerRefFound = true; return(false);
                }
                return(true);
            }).ToArray();
#endif
            IBuildTarget buildTarget;
            string       prefix;
            GetBuildTargetAndPrefix(qfBuildTarget, tifBuildTarget, record, out buildTarget, out prefix);
            string fileNameNoExt = BuildTargetsWriter.GetFileNameNoExt(prefix, record, true, stageIndexAndLogIndex);
            string aliasesPath   = buildTarget.GetSourcePath() + fileNameNoExt + ".references";
            string contents      = string.Join("\r\n", aliases)
#if !NEWBT
                                   + (playerRefFound && aliases.Any() ? "\r\n" : "") + "\r\n\r\n"
#endif
            ;
            FileWriter.WriteAllTextOrThrowIfExists(aliasesPath, contents);
        }
 private static void GetBuildTargetAndPrefix(IBuildTarget qfBuildTarget, IBuildTarget tifBuildTarget, TES4Record record, out IBuildTarget buildTarget, out string prefix)
 {
     if (record.RecordType == TES4RecordType.QUST)
     {
         buildTarget = qfBuildTarget; prefix = TES5ReferenceFactory.qf_Prefix;
     }
     else if (record.RecordType == TES4RecordType.INFO)
     {
         buildTarget = tifBuildTarget; prefix = TES5ReferenceFactory.tif_Prefix;
     }
     else
     {
         throw new InvalidOperationException("Invalid record type:  " + record.RecordType.Name);
     }
 }
        public Nullable <KeyValuePair <int, TES5BasicType> > GetTypeFromSCRO(int scriptTES4FormID, StageIndexAndLogIndex?stageIndexAndLogIndex, string propertyName)
        {
            TES4Record scriptTES4Record = GetRecordByFormID(scriptTES4FormID);

            return(GetTypeFromSCRO(scriptTES4Record, stageIndexAndLogIndex, propertyName, !(scriptTES4FormID == 73629 && stageIndexAndLogIndex != null && stageIndexAndLogIndex.StageIndex == 150 && stageIndexAndLogIndex.LogIndex == 0 && propertyName == "SE02FIN")));//WTM:  Note:  Special Case:  property not found in SCRO records
        }