/// <summary> /// Writes all variables into a file. /// </summary> /// <param name="drc">source</param> /// <param name="baseFolder">Path in the file.</param> /// <param name="fileName">file name to be written</param> public void Write(DBRecordCollection drc, string baseFolder, string fileName = null) { // construct the full path string fullPath = Path.Combine(baseFolder, drc.Id); string destinationFolder = Path.GetDirectoryName(fullPath); if (fileName != null) { fullPath = Path.Combine(baseFolder, fileName); destinationFolder = baseFolder; } // Create the folder path if necessary if (!Directory.Exists(destinationFolder)) { Directory.CreateDirectory(destinationFolder); } // Open the file using (StreamWriter outStream = new StreamWriter(fullPath, false)) { // Write all the variables foreach (Variable variable in drc) { outStream.WriteLine(variable.ToString()); } } }
/// <summary> /// Gets a DBRecord for the specified item ID string. /// </summary> /// <remarks> /// Changed by VillageIdiot /// Changed search order so that IT records have precedence of TQ records. /// Add Custom Map database. Custom Map records have precedence over IT records. /// </remarks> /// <param name="itemId">Item Id which we are looking up</param> /// <returns>Returns the DBRecord for the item Id</returns> public DBRecordCollection GetRecordFromFile(string itemId) { itemId = TQData.NormalizeRecordPath(itemId); if (this.ArzFileMod != null) { DBRecordCollection recordMod = arzProv.GetItem(this.ArzFileMod, itemId); if (recordMod != null) { // Custom Map records have highest precedence. return(recordMod); } } if (this.ArzFileIT != null) { // see if it's in IT ARZ file DBRecordCollection recordIT = arzProv.GetItem(this.ArzFileIT, itemId); if (recordIT != null) { // IT file takes precedence over TQ. return(recordIT); } } return(arzProv.GetItem(ArzFile, itemId)); }
/// <summary> /// Gets the DBRecord for a particular ID. /// </summary> /// <param name="recordId">string ID of the record will be normalized internally</param> /// <returns>DBRecord corresponding to the string ID.</returns> public DBRecordCollection GetItem(string recordId) { DBRecordCollection result = null; if (string.IsNullOrEmpty(recordId)) { return(result); } recordId = TQData.NormalizeRecordPath(recordId); DBRecordCollection databaseRecord; if (cache.ContainsKey(recordId)) { databaseRecord = this.cache[recordId]; } else { RecordInfo rawRecord; if (recordInfo.ContainsKey(recordId)) { rawRecord = this.recordInfo[recordId]; } else { // record not found return(null); } databaseRecord = rawRecord.Decompress(this); this.cache.Add(recordId, databaseRecord); } return(databaseRecord); }
/// <summary> /// Gets the Infor for a specific item id. /// </summary> /// <param name="itemId">Item ID which we are looking up. Will be normalized internally.</param> /// <returns>Returns Infor for item ID and NULL if not found.</returns> public Info GetInfo(string itemId) { if (string.IsNullOrEmpty(itemId)) return null; itemId = TQData.NormalizeRecordPath(itemId); return this.infoDB.GetOrAddAtomic(itemId, k => { DBRecordCollection record = null; // Add support for searching a custom map database if (this.ArzFileMod != null) record = arzProv.GetItem(this.ArzFileMod, k); // Try the expansion pack database first. if (record == null && this.ArzFileIT != null) record = arzProv.GetItem(this.ArzFileIT, k); // Try looking in TQ database now if (record == null || this.ArzFileIT == null) record = arzProv.GetItem(this.ArzFile, k); if (record == null) return null; return new Info(record); }); }
/// <summary> /// Gets the Infor for a specific item id. /// </summary> /// <param name="itemId">Item ID which we are looking up. Will be normalized internally.</param> /// <returns>Returns Infor for item ID and NULL if not found.</returns> public Info GetInfo(string itemId) { Info result = null; if (string.IsNullOrEmpty(itemId)) { return(result); } itemId = TQData.NormalizeRecordPath(itemId); Info info; if (infoDB.ContainsKey(itemId)) { info = this.infoDB[itemId]; } else { DBRecordCollection record = null; // Add support for searching a custom map database if (this.ArzFileMod != null) { record = this.ArzFileMod.GetItem(itemId); } // Try the expansion pack database first. if (record == null && this.ArzFileIT != null) { record = this.ArzFileIT.GetItem(itemId); } // Try looking in TQ database now if (record == null || this.ArzFileIT == null) { record = this.ArzFile.GetItem(itemId); } if (record == null) { return(null); } info = new Info(record); this.infoDB.Add(itemId, info); } return(info); }
/// <summary> /// Handler for clicking on a treeView item /// </summary> /// <param name="sender">sender object</param> /// <param name="e">TreeViewEventArgs data</param> private void TreeView1_AfterSelect(object sender, TreeViewEventArgs e) { // Make sure we have selected the last child // otherwise this will be a directory. if (this.treeViewTOC.SelectedNode.GetNodeCount(false) == 0) { this.destFile = this.treeViewTOC.SelectedNode.FullPath; try { List <string> recordText = new List <string>(); if (fileType == CompressedFileType.ArzFile) { this.dataGridView1.Visible = true; this.textBoxDetails.Visible = false; this.record = arzProv.GetRecordNotCached(arzFile, this.destFile); foreach (Variable variable in this.record) { if (variable.IsValueNonZero() || !hideZeroValuesToolStripMenuItem.Checked) { recordText.Add(variable.ToString()); } } } else if (fileType == CompressedFileType.ArcFile) { string extension = Path.GetExtension(this.destFile).ToUpper(); string arcDataPath = Path.Combine(Path.GetFileNameWithoutExtension(arcFile.FileName), this.destFile); if (extension == ".TXT") { byte[] rawData = arcProv.GetData(arcFile, arcDataPath); if (rawData == null) { return; } // now read it like a text file using (StreamReader reader = new StreamReader(new MemoryStream(rawData), Encoding.Default)) { string line; while ((line = reader.ReadLine()) != null) { recordText.Add(line); } } this.dataGridView1.Visible = false; this.textBoxDetails.Visible = true; } else if (extension == ".TEX") { byte[] rawData = arcProv.GetData(arcFile, arcDataPath); if (rawData == null) { return; } Bitmap bitmap = BitmapService.LoadFromTexMemory(rawData, 0, rawData.Length); if (bitmap != null) { this.dataGridView1.Visible = false; this.pictureBoxItem.Visible = true; this.pictureBoxItem.Image = bitmap; } } else { this.pictureBoxItem.Visible = false; } } else { this.dataGridView1.Visible = false; this.pictureBoxItem.Visible = false; this.destFile = null; this.textBoxDetails.Lines = null; return; } // Now display our results. if (recordText.Count != 0) { this.pictureBoxItem.Visible = false; if (fileType == CompressedFileType.ArzFile) { this.textBoxDetails.Visible = false; this.dataGridView1.Visible = true; PopulateGridView(recordText); } else { this.dataGridView1.Visible = false; this.textBoxDetails.Visible = true; string[] output = new string[recordText.Count]; recordText.CopyTo(output); this.textBoxDetails.Lines = output; } } else { this.textBoxDetails.Lines = null; } } catch (Exception ex) { this.Log.ErrorException(ex); } } else { this.destFile = null; this.textBoxDetails.Lines = null; } }
/// <summary> /// Decompresses an individual record. /// </summary> /// <param name="arzFile">ARZ file which we are decompressing.</param> /// <returns>decompressed DBRecord.</returns> public DBRecordCollection Decompress(ArzFile arzFile) { // record variables have this format: // 0x00 int16 specifies data type: // 0x0000 = int - data will be an int32 // 0x0001 = float - data will be a Single // 0x0002 = string - data will be an int32 that is index into string table // 0x0003 = bool - data will be an int32 // 0x02 int16 specifies number of values (usually 1, but sometimes more (for arrays) // 0x04 int32 key string ID (the id into the string table for this variable name // 0x08 data value byte[] data = this.DecompressBytes(arzFile); int numberOfDWords = data.Length / 4; if (data.Length % 4 != 0) { var ex = new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Error while parsing arz record {0}, data Length = {1} which is not a multiple of 4", this.ID, (int)data.Length)); Log.ErrorException(ex); throw ex; } DBRecordCollection record = new DBRecordCollection(this.ID, this.RecordType); // Create a memory stream to read the binary data using (BinaryReader inReader = new BinaryReader(new MemoryStream(data, false))) { int i = 0; while (i < numberOfDWords) { short dataType = inReader.ReadInt16(); short valCount = inReader.ReadInt16(); int variableID = inReader.ReadInt32(); string variableName = arzFile.Getstring(variableID); if (variableName == null) { var ex = new ArgumentNullException(string.Format(CultureInfo.InvariantCulture, "Error while parsing arz record {0}, variable is NULL", this.ID)); Log.ErrorFormat(CultureInfo.InvariantCulture, "Error in ARZFile - {0}", arzFile.fileName); Log.ErrorException(ex); throw ex; } if (dataType < 0 || dataType > 3) { var ex = new ArgumentOutOfRangeException(string.Format(CultureInfo.InvariantCulture, "Error while parsing arz record {0}, variable {1}, bad dataType {2}", this.ID, variableName, dataType)); Log.ErrorFormat(CultureInfo.InvariantCulture, "Error in ARZFile - {0}", arzFile.fileName); Log.ErrorException(ex); throw ex; } Variable v = new Variable(variableName, (VariableDataType)dataType, valCount); if (valCount < 1) { var ex = new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Error while parsing arz record {0}, variable {1}, bad valCount {2}", this.ID, variableName, valCount)); Log.ErrorFormat(CultureInfo.InvariantCulture, "Error in ARZFile - {0}", arzFile.fileName); Log.ErrorException(ex); throw ex; } // increment our dword count i += 2 + valCount; for (int j = 0; j < valCount; ++j) { switch (v.DataType) { case VariableDataType.Integer: case VariableDataType.Boolean: { int val = inReader.ReadInt32(); v[j] = val; break; } case VariableDataType.Float: { float val = inReader.ReadSingle(); v[j] = val; break; } case VariableDataType.StringVar: { int id = inReader.ReadInt32(); string val = arzFile.Getstring(id); if (val == null) { val = string.Empty; } else { val = val.Trim(); } v[j] = val; break; } default: { int val = inReader.ReadInt32(); v[j] = val; break; } } } record.Set(v); } } return(record); }
/// <summary> /// Builds the table from the database using the passed table Id. /// </summary> public static LootTableCollection LoadTable(string tableId) { var ntab = new LootTableCollection(tableId); // Get the data DBRecordCollection record = Database.DB.GetRecordFromFile(ntab.tableId); if (record == null) { return(ntab); } // Go through and get all of the randomizerWeight randomizerName pairs that have a weight > 0. Dictionary <int, float> weights = new Dictionary <int, float>(); Dictionary <int, string> names = new Dictionary <int, string>(); foreach (Variable variable in record) { string upperCase = variable.Name.ToUpperInvariant(); if (upperCase.StartsWith("RANDOMIZERWEIGHT", StringComparison.Ordinal)) { string numPart = upperCase.Substring(16); int num; if (int.TryParse(numPart, out num)) { // Make sure the value is an integer or float float value = -1.0F; if (variable.DataType == VariableDataType.Integer) { value = (float)variable.GetInt32(0); } else if (variable.DataType == VariableDataType.Float) { value = variable.GetSingle(0); } if (value > 0) { weights.Add(num, value); } } } else if (upperCase.StartsWith("RANDOMIZERNAME", StringComparison.Ordinal)) { string numPart = upperCase.Substring(14); int num; if (int.TryParse(numPart, out num)) { // now get the value string value = variable.GetString(0); if (!string.IsNullOrEmpty(value)) { names.Add(num, value); } } } } // Now do an INNER JOIN on the 2 dictionaries to find valid pairs. IEnumerable <KeyValuePair <string, float> > buildTableQuery = from weight in weights join name in names on weight.Key equals name.Key select new KeyValuePair <string, float>(name.Value, weight.Value); // Iterate the query to build the new unweighted table. foreach (KeyValuePair <string, float> kvp in buildTableQuery) { // Check for a double entry in the table. if (ntab.data.ContainsKey(kvp.Key)) { // for a double entry just add the chance. ntab.data[kvp.Key] += kvp.Value; } else { ntab.data.Add(kvp.Key, kvp.Value); } } // Calculate the total weight. ntab.totalWeight = buildTableQuery.Sum(kvp => kvp.Value); return(ntab); }