/// <summary> /// Gets the list of status effect UI elements /// </summary> /// <returns>A list containing XivUi data</returns> public async Task <List <XivUi> > GetStatusList() { var statusLock = new object(); var statusList = new List <XivUi>(); // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch const int nameLengthDataOffset = 6; const int typeDataOffset = 13; const int dataLength = 24; var statusExData = await _ex.ReadExData(XivEx.status); await Task.Run(() => Parallel.ForEach(statusExData.Values, (status) => { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Status }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(status))) { br.BaseStream.Seek(nameLengthDataOffset, SeekOrigin.Begin); var nameLength = br.ReadInt16(); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { return; } br.BaseStream.Seek(typeDataOffset, SeekOrigin.Begin); var type = br.ReadByte(); br.BaseStream.Seek(dataLength, SeekOrigin.Begin); var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.IconNumber = iconNumber; xivUi.Name = name; if (name.Equals(string.Empty)) { return; } //Status effects have a byte that determines whether the effect is detrimental or beneficial if (type == 1) { xivUi.ItemSubCategory = XivStrings.Beneficial; } else if (type == 2) { xivUi.ItemSubCategory = XivStrings.Detrimental; } else { xivUi.ItemSubCategory = XivStrings.None; xivUi.Name = xivUi.Name + " " + type; } } lock (statusLock) { statusList.Add(xivUi); } })); statusList.Sort(); return(statusList); }
/// <summary> /// Gets the list of available map data /// </summary> /// <remarks> /// The map data is obtained from the map exd files /// There may be unlisted maps which this does not check for /// </remarks> /// <returns>A list containing XivUi data</returns> public async Task <List <XivUi> > GetMapList() { var mapLock = new object(); // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch const int regionMapDataOffset = 12; const int dataLength = 32; var mapList = new List <XivUi>(); var placeNameData = await _ex.ReadExData(XivEx.placename); var mapData = await _ex.ReadExData(XivEx.map); var mapNameList = new List <string>(); // Loops through all available maps in the map exd files // At present only one file exists (map_0) await Task.Run(() => Parallel.ForEach(mapData.Values, (map) => { int regionIndex; int mapIndex; var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Maps }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(map))) { br.BaseStream.Seek(regionMapDataOffset, SeekOrigin.Begin); regionIndex = br.ReadInt16(); mapIndex = br.ReadInt16(); if (mapIndex == 0) { return; } br.BaseStream.Seek(dataLength, SeekOrigin.Begin); // The size of the map path string // Size of the entire data chunk - size of the data portion var mapPathLength = map.Length - dataLength; if (mapPathLength < 4) { return; } xivUi.UiPath = Encoding.UTF8.GetString(br.ReadBytes(mapPathLength)).Replace("\0", ""); } // Gets the name from the placename exd file var regionName = GetPlaceName(placeNameData[regionIndex]); var mapName = GetPlaceName(placeNameData[mapIndex]); if (mapName.Equals(string.Empty)) { return; } xivUi.Name = mapName; xivUi.ItemSubCategory = regionName; if (mapNameList.Contains(mapName)) { xivUi.Name = mapName + " " + xivUi.UiPath.Substring(xivUi.UiPath.Length - 2); } lock (mapLock) { mapNameList.Add(mapName); mapList.Add(xivUi); } })); mapList.Sort(); return(mapList); }
public void Load(BinaryReaderBE reader) { long origin = reader.BaseStream.Position; Version = reader.ReadInt16(); Type = (CollectionType)reader.ReadInt16(); Flags = reader.ReadUInt16(); colorCount = reader.ReadInt16(); colorTableCount = reader.ReadInt16(); colorTableOffset = reader.ReadInt32(); highLevelShapeCount = reader.ReadInt16(); highLevelShapeOffsetTableOffset = reader.ReadInt32(); lowLevelShapeCount = reader.ReadInt16(); lowLevelShapeOffsetTableOffset = reader.ReadInt32(); bitmapCount = reader.ReadInt16(); bitmapOffsetTableOffset = reader.ReadInt32(); pixelsToWorld = reader.ReadInt16(); size = reader.ReadInt32(); reader.BaseStream.Seek(253 * 2, SeekOrigin.Current); colorTables.Clear(); reader.BaseStream.Seek(origin + colorTableOffset, SeekOrigin.Begin); for (int i = 0; i < colorTableCount; ++i) { ColorValue[] table = new ColorValue[colorCount]; for (int j = 0; j < colorCount; ++j) { table[j].Load(reader); } colorTables.Add(table); } bitmaps.Clear(); reader.BaseStream.Seek(origin + bitmapOffsetTableOffset, SeekOrigin.Begin); for (int i = 0; i < bitmapCount; ++i) { int bitmapPosition = reader.ReadInt32(); long nextPositionInOffsetTable = reader.BaseStream.Position; reader.BaseStream.Seek(origin + bitmapPosition, SeekOrigin.Begin); Bitmap bitmap = new Bitmap(); bitmap.Load(reader); bitmaps.Add(bitmap); reader.BaseStream.Seek(nextPositionInOffsetTable, SeekOrigin.Begin); } lowLevelShapes.Clear(); reader.BaseStream.Seek(origin + lowLevelShapeOffsetTableOffset, SeekOrigin.Begin); for (int i = 0; i < lowLevelShapeCount; i++) { long shapeDefinitionPosition = origin + reader.ReadInt32(); long nextPositionInOffsetTable = reader.BaseStream.Position; reader.BaseStream.Seek(shapeDefinitionPosition, SeekOrigin.Begin); LowLevelShapeDefinition lowLevelShapeDefinition = new LowLevelShapeDefinition(); lowLevelShapeDefinition.Load(reader); lowLevelShapes.Add(lowLevelShapeDefinition); reader.BaseStream.Seek(nextPositionInOffsetTable, SeekOrigin.Begin); } }
/// <summary> /// Gets the list of action UI elements /// </summary> /// <remarks> /// The actions are obtained from different sources, but is not all inclusive /// There may be some actions that are missing /// </remarks> /// <returns>A list containing XivUi data</returns> public async Task <List <XivUi> > GetActionList() { var actionLock = new object(); // Data from the action_0 exd var actionExData = await _ex.ReadExData(XivEx.action); var actionCategoryExData = await _ex.ReadExData(XivEx.actioncategory); var actionList = new List <XivUi>(); var actionNames = new List <string>(); await Task.Run(() => Parallel.ForEach(actionExData.Values, (action) => { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Actions }; int actionCategory; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(action))) { br.BaseStream.Seek(8, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { return; } br.BaseStream.Seek(26, SeekOrigin.Begin); actionCategory = br.ReadByte(); br.BaseStream.Seek(56, SeekOrigin.Begin); var nameLength = action.Length - 56; var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.Name = name; xivUi.IconNumber = iconNumber; } if (xivUi.Name.Equals(string.Empty)) { return; } if (actionNames.Contains(xivUi.Name)) { return; } var actionCategoryData = actionCategoryExData[actionCategory]; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(actionCategoryData))) { br.BaseStream.Seek(4, SeekOrigin.Begin); var nameLength = actionCategoryData.Length - 4; var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); if (name.Equals(string.Empty)) { xivUi.ItemSubCategory = XivStrings.None; } else { xivUi.ItemSubCategory = name; } } lock (actionLock) { actionNames.Add(xivUi.Name); actionList.Add(xivUi); } })); // Data from generalaction_0 var generalActionExData = await _ex.ReadExData(XivEx.generalaction); await Task.Run(() => Parallel.ForEach(generalActionExData.Values, (action) => { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Actions, ItemSubCategory = XivStrings.General }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(action))) { br.BaseStream.Seek(6, SeekOrigin.Begin); var nameLength = br.ReadInt16(); br.BaseStream.Seek(10, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { return; } br.BaseStream.Seek(20, SeekOrigin.Begin); var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.Name = name; xivUi.IconNumber = iconNumber; } lock (actionLock) { actionNames.Add(xivUi.Name); actionList.Add(xivUi); } })); // Data from buddyaction_0 var buddyActionExData = await _ex.ReadExData(XivEx.buddyaction); await Task.Run(() => Parallel.ForEach(buddyActionExData.Values, (action) => { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Actions, ItemSubCategory = XivStrings.Buddy }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(action))) { br.BaseStream.Seek(6, SeekOrigin.Begin); var nameLength = br.ReadInt16(); br.BaseStream.Seek(10, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { return; } br.BaseStream.Seek(20, SeekOrigin.Begin); var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.Name = name; xivUi.IconNumber = iconNumber; } if (actionNames.Contains(xivUi.Name)) { return; } lock (actionLock) { actionNames.Add(xivUi.Name); actionList.Add(xivUi); } })); // Data from companyaction_0 var companyActionExData = await _ex.ReadExData(XivEx.companyaction); await Task.Run(() => Parallel.ForEach(companyActionExData.Values, (action) => { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Actions, ItemSubCategory = XivStrings.Company }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(action))) { br.BaseStream.Seek(6, SeekOrigin.Begin); var nameLength = br.ReadInt16(); br.BaseStream.Seek(14, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { return; } br.BaseStream.Seek(20, SeekOrigin.Begin); var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.Name = name; xivUi.IconNumber = iconNumber; } if (actionNames.Contains(xivUi.Name)) { return; } lock (actionLock) { actionNames.Add(xivUi.Name); actionList.Add(xivUi); } })); // Data from craftaction_100000 var craftActionExData = await _ex.ReadExData(XivEx.craftaction); await Task.Run(() => Parallel.ForEach(craftActionExData.Values, (action) => { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Actions, ItemSubCategory = XivStrings.Craft }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(action))) { br.BaseStream.Seek(6, SeekOrigin.Begin); var nameLength = br.ReadInt16(); br.BaseStream.Seek(48, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { return; } br.BaseStream.Seek(60, SeekOrigin.Begin); var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.Name = name; xivUi.IconNumber = iconNumber; } if (actionNames.Contains(xivUi.Name)) { return; } lock (actionLock) { actionNames.Add(xivUi.Name); actionList.Add(xivUi); } })); // Data from eventaction_0 var eventActionExData = await _ex.ReadExData(XivEx.eventaction); await Task.Run(() => Parallel.ForEach(eventActionExData.Values, (action) => { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Actions, ItemSubCategory = XivStrings.Event }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(action))) { br.BaseStream.Seek(4, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { return; } br.BaseStream.Seek(16, SeekOrigin.Begin); var nameLength = action.Length - 16; var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.Name = name; xivUi.IconNumber = iconNumber; } if (actionNames.Contains(xivUi.Name)) { return; } lock (actionLock) { actionNames.Add(xivUi.Name); actionList.Add(xivUi); } })); // Data from emote_0 var emoteExData = await _ex.ReadExData(XivEx.emote); await Task.Run(() => Parallel.ForEach(emoteExData.Values, (action) => { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Actions, ItemSubCategory = XivStrings.Emote }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(action))) { br.BaseStream.Seek(28, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { return; } br.BaseStream.Seek(40, SeekOrigin.Begin); var nameLength = action.Length - 40; var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.Name = name; xivUi.IconNumber = iconNumber; } if (actionNames.Contains(xivUi.Name)) { return; } lock (actionLock) { actionNames.Add(xivUi.Name); actionList.Add(xivUi); } })); // Data from marker_0 var markerExData = await _ex.ReadExData(XivEx.marker); await Task.Run(() => Parallel.ForEach(markerExData.Values, (action) => { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Actions, ItemSubCategory = XivStrings.Marker }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(action))) { br.BaseStream.Seek(6, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { return; } var nameLength = action.Length - 6; var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.Name = name; xivUi.IconNumber = iconNumber; } if (actionNames.Contains(xivUi.Name)) { return; } lock (actionLock) { actionNames.Add(xivUi.Name); actionList.Add(xivUi); } })); // Data from fieldmarker_0 var fieldMarkerExData = await _ex.ReadExData(XivEx.fieldmarker); await Task.Run(() => Parallel.ForEach(fieldMarkerExData.Values, (action) => { var xivUi = new XivUi() { Category = "UI", ItemCategory = XivStrings.Actions, ItemSubCategory = XivStrings.FieldMarker }; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(action))) { br.BaseStream.Seek(8, SeekOrigin.Begin); var iconNumber = br.ReadUInt16(); if (iconNumber == 0) { return; } br.BaseStream.Seek(12, SeekOrigin.Begin); var nameLength = action.Length - 12; var name = Encoding.UTF8.GetString(br.ReadBytes(nameLength)).Replace("\0", ""); xivUi.Name = name; xivUi.IconNumber = iconNumber; } if (actionNames.Contains(xivUi.Name)) { return; } lock (actionLock) { actionNames.Add(xivUi.Name); actionList.Add(xivUi); } })); actionList.Sort(); return(actionList); }
internal void LoadEntry(BinaryReaderBE reader) { Offset = reader.ReadInt32(); reader.ReadInt32(); // size Index = reader.ReadInt16(); }
public void Load(BinaryReaderBE reader) { long origin = reader.BaseStream.Position; Version = reader.ReadInt16(); Type = (CollectionType)reader.ReadInt16(); Flags = reader.ReadUInt16(); colorCount = reader.ReadInt16(); colorTableCount = reader.ReadInt16(); colorTableOffset = reader.ReadInt32(); highLevelShapeCount = reader.ReadInt16(); highLevelShapeOffsetTableOffset = reader.ReadInt32(); lowLevelShapeCount = reader.ReadInt16(); lowLevelShapeOffsetTableOffset = reader.ReadInt32(); bitmapCount = reader.ReadInt16(); bitmapOffsetTableOffset = reader.ReadInt32(); pixelsToWorld = reader.ReadInt16(); size = reader.ReadInt32(); reader.BaseStream.Seek(253 * 2, SeekOrigin.Current); colorTables.Clear(); reader.BaseStream.Seek(origin + colorTableOffset, SeekOrigin.Begin); for (int i = 0; i < colorTableCount; ++i) { ColorValue[] table = new ColorValue[colorCount]; for (int j = 0; j < colorCount; ++j) { table[j].Load(reader); } colorTables.Add(table); } reader.BaseStream.Seek(origin + bitmapOffsetTableOffset, SeekOrigin.Begin); bitmaps.Clear(); for (int i = 0; i < bitmapCount; ++i) { int offset = reader.ReadInt32(); long position = reader.BaseStream.Position; reader.BaseStream.Seek(origin + offset, SeekOrigin.Begin); Bitmap bitmap = new Bitmap(); bitmap.Load(reader); bitmaps.Add(bitmap); reader.BaseStream.Seek(position, SeekOrigin.Begin); } reader.BaseStream.Seek(origin + lowLevelShapeOffsetTableOffset, SeekOrigin.Begin); frames.Clear(); for (int i = 0; i < lowLevelShapeCount; ++i) { int offset = reader.ReadInt32(); long position = reader.BaseStream.Position; reader.BaseStream.Seek(origin + offset, SeekOrigin.Begin); ShapeFrame frame = new ShapeFrame(); frame.Load(reader); frames.Add(frame); reader.BaseStream.Seek(position, SeekOrigin.Begin); } reader.BaseStream.Seek(origin + highLevelShapeOffsetTableOffset, SeekOrigin.Begin); sequences.Clear(); for (int i = 0; i < highLevelShapeCount; ++i) { int offset = reader.ReadInt32(); long position = reader.BaseStream.Position; reader.BaseStream.Seek(origin + offset, SeekOrigin.Begin); ShapeSequence sequence = new ShapeSequence(); sequence.Load(reader); sequences.Add(sequence); reader.BaseStream.Seek(position, SeekOrigin.Begin); } }
public void Load(BinaryReaderBE reader) { X = reader.ReadInt16(); Y = reader.ReadInt16(); Texture = (ShapeDescriptor)reader.ReadUInt16(); }
/// <summary> /// Gets the list of indoor furniture /// </summary> /// <remarks> /// Housing items can be obtained one of two ways /// One: checking the housingfurniture exd for the item index, and going to that item to grab the data /// Two: iterating through the entire item list seeing if the item contains an index to a housing item (offset 112, 4 bytes) /// This method does option one /// </remarks> /// <returns>A list of XivFurniture objects containing indoor furniture item info</returns> private List <XivFurniture> GetIndoorFurniture() { // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch const int itemIndexOffset = 10; const int modelNumberOffset = 12; const int itemCategoryOffset = 14; const int itemNameDataOffset = 14; const int itemDataLength = 160; const int itemIconDataOffset = 136; var ex = new Ex(_gameDirectory, _xivLanguage); var housingDictionary = ex.ReadExData(XivEx.housingfurniture); var itemDictionary = ex.ReadExData(XivEx.item); var furnitureList = new List <XivFurniture>(); foreach (var housingItem in housingDictionary.Values) { var item = new XivFurniture { Category = XivStrings.Housing, ItemCategory = XivStrings.Furniture_Indoor, ModelInfo = new XivModelInfo() }; using (var br = new BinaryReaderBE(new MemoryStream(housingItem))) { br.BaseStream.Seek(itemIndexOffset, SeekOrigin.Begin); var itemIndex = br.ReadInt16(); br.BaseStream.Seek(modelNumberOffset, SeekOrigin.Begin); item.ModelInfo.ModelID = br.ReadInt16(); br.BaseStream.Seek(itemCategoryOffset, SeekOrigin.Begin); var housingCategory = br.ReadByte(); using (var br1 = new BinaryReaderBE(new MemoryStream(itemDictionary[itemIndex]))) { br1.BaseStream.Seek(itemNameDataOffset, SeekOrigin.Begin); var nameOffset = br1.ReadInt16(); br1.BaseStream.Seek(itemIconDataOffset, SeekOrigin.Begin); item.IconNumber = br1.ReadUInt16(); var gearNameOffset = itemDataLength + nameOffset; var gearNameLength = itemDictionary[itemIndex].Length - gearNameOffset; br1.BaseStream.Seek(gearNameOffset, SeekOrigin.Begin); var nameString = Encoding.UTF8.GetString(br1.ReadBytes(gearNameLength)).Replace("\0", ""); item.Name = new string(nameString.Where(c => !char.IsControl(c)).ToArray()); } } if (!item.Name.Equals(string.Empty)) { furnitureList.Add(item); } } furnitureList.Sort(); return(furnitureList); }
/// <summary> /// Gets the list to be displayed in the Minion category /// </summary> /// <remarks> /// The model data for the minion is held separately in modelchara_0.exd /// The data within companion_0 exd contains a reference to the index for lookup in modelchara /// </remarks> /// <returns>A list containing XivMinion data</returns> public async Task <List <XivMinion> > GetUncachedMinionList() { var minionLock = new object(); var minionList = new List <XivMinion>(); // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch const int dataLength = 48; const int nameDataOffset = 6; const int modelCharaIndexOffset = 16; var minionEx = await _ex.ReadExData(XivEx.companion); var modelCharaEx = await XivModelChara.GetModelCharaData(_gameDirectory); // Loops through all available minions in the companion exd files // At present only one file exists (companion_0) await Task.Run(() => Parallel.ForEach(minionEx.Values, (minion) => { var xivMinion = new XivMinion { PrimaryCategory = XivStrings.Companions, SecondaryCategory = XivStrings.Minions }; int modelCharaIndex; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(minion))) { br.BaseStream.Seek(nameDataOffset, SeekOrigin.Begin); var nameOffset = br.ReadInt16(); br.BaseStream.Seek(modelCharaIndexOffset, SeekOrigin.Begin); modelCharaIndex = br.ReadInt16(); br.BaseStream.Seek(dataLength, SeekOrigin.Begin); var nameString = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(Encoding.UTF8 .GetString(br.ReadBytes(nameOffset)).Replace("\0", "")); xivMinion.Name = new string(nameString.Where(c => !char.IsControl(c)).ToArray()); } if (modelCharaIndex == 0) { return; } // This will get the model data using the index obtained for the current minion xivMinion.ModelInfo = XivModelChara.GetModelInfo(modelCharaEx, modelCharaIndex); lock (minionLock) { minionList.Add(xivMinion); } })); minionList.Sort(); return(minionList); }
public void Load(BinaryReaderBE reader) { Type = (SideType)reader.ReadInt16(); Flags = (SideFlags)reader.ReadUInt16(); Primary.Load(reader); Secondary.Load(reader); Transparent.Load(reader); reader.BaseStream.Seek(16, SeekOrigin.Current); // exclusion zone ControlPanelType = reader.ReadInt16(); ControlPanelPermutation = reader.ReadInt16(); PrimaryTransferMode = reader.ReadInt16(); SecondaryTransferMode = reader.ReadInt16(); TransparentTransferMode = reader.ReadInt16(); PolygonIndex = reader.ReadInt16(); LineIndex = reader.ReadInt16(); PrimaryLightsourceIndex = reader.ReadInt16(); SecondaryLightsourceIndex = reader.ReadInt16(); TransparentLightsourceIndex = reader.ReadInt16(); AmbientDelta = reader.ReadInt32(); reader.ReadInt16(); // unused }
/// <summary> /// Gets the list of indoor furniture /// </summary> /// <remarks> /// Housing items can be obtained one of two ways /// One: checking the housingfurniture exd for the item index, and going to that item to grab the data /// Two: iterating through the entire item list seeing if the item contains an index to a housing item (offset 112, 4 bytes) /// This method does option one /// </remarks> /// <returns>A list of XivFurniture objects containing indoor furniture item info</returns> private async Task <List <XivFurniture> > GetPaintings() { var paintingsLock = new object(); // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch const int itemIndexOffset = 0; const int iconNumberOffset = 4; const int itemNameDataOffset = 14; const int itemDataLength = 160; const int itemIconDataOffset = 136; var ex = new Ex(_gameDirectory, _xivLanguage); var pictureDictionary = await ex.ReadExData(XivEx.picture); var itemDictionary = await ex.ReadExData(XivEx.item); var furnitureList = new List <XivFurniture>(); await Task.Run(() => Parallel.ForEach(pictureDictionary.Values, (housingItem) => { var item = new XivFurniture { Category = XivStrings.Housing, ItemCategory = XivStrings.Paintings, ModelInfo = new XivModelInfo() }; using (var br = new BinaryReaderBE(new MemoryStream(housingItem))) { br.BaseStream.Seek(itemIndexOffset, SeekOrigin.Begin); var itemIndex = br.ReadInt32(); br.BaseStream.Seek(iconNumberOffset, SeekOrigin.Begin); item.ModelInfo.ModelID = br.ReadInt32(); using (var br1 = new BinaryReaderBE(new MemoryStream(itemDictionary[itemIndex]))) { br1.BaseStream.Seek(itemNameDataOffset, SeekOrigin.Begin); var nameOffset = br1.ReadInt16(); br1.BaseStream.Seek(itemIconDataOffset, SeekOrigin.Begin); item.IconNumber = br1.ReadUInt16(); var gearNameOffset = itemDataLength + nameOffset; var gearNameLength = itemDictionary[itemIndex].Length - gearNameOffset; br1.BaseStream.Seek(gearNameOffset, SeekOrigin.Begin); var nameString = Encoding.UTF8.GetString(br1.ReadBytes(gearNameLength)).Replace("\0", ""); item.Name = new string(nameString.Where(c => !char.IsControl(c)).ToArray()); } } if (!item.Name.Equals(string.Empty)) { lock (paintingsLock) { furnitureList.Add(item); } } })); furnitureList.Sort(); return(furnitureList); }
public void Load(BinaryReaderBE reader) { Type = (MediaType)reader.ReadInt16(); Flags = (MediaFlags)reader.ReadUInt16(); LightIndex = reader.ReadInt16(); direction = reader.ReadInt16(); CurrentMagnitude = reader.ReadInt16(); Low = reader.ReadInt16(); High = reader.ReadInt16(); reader.ReadInt16(); // X reader.ReadInt16(); // Y reader.ReadInt16(); // Height MinimumLightIntensity = reader.ReadFixed(); reader.ReadInt16(); // Texture reader.ReadInt16(); // TransferMode reader.BaseStream.Seek(2 * 2, SeekOrigin.Current); }
public void Load(BinaryReaderBE reader) { Index = reader.ReadInt16(); Face = reader.ReadInt16(); Colour = reader.ReadInt16(); }
/// <summary> /// Gets the list of indoor furniture /// </summary> /// <remarks> /// Housing items can be obtained one of two ways /// One: checking the housingfurniture exd for the item index, and going to that item to grab the data /// Two: iterating through the entire item list seeing if the item contains an index to a housing item (offset 112, 4 bytes) /// This method does option two as the item index was removed from the picture exd file in patch 5.2 /// </remarks> /// <returns>A list of XivFurniture objects containing indoor furniture item info</returns> private async Task <List <XivFurniture> > GetPaintings() { var paintingsLock = new object(); // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch int iconNumberOffset = 0; const int itemNameDataOffset = 14; const int housingIndexOffset = 112; int itemDataLength = 168; const int itemIconDataOffset = 136; var ex = new Ex(_gameDirectory, _xivLanguage); var pictureDictionary = await ex.ReadExData(XivEx.picture); var itemDictionary = await ex.ReadExData(XivEx.item); if (_xivLanguage == XivLanguage.Korean) { itemDataLength = 160; } else if (_xivLanguage == XivLanguage.Chinese) { itemDataLength = 160; } var furnitureList = new List <XivFurniture>(); await Task.Run(() => Parallel.ForEach(itemDictionary.Values, (item) => { var painting = new XivFurniture { PrimaryCategory = XivStrings.Housing, SecondaryCategory = XivStrings.Paintings, ModelInfo = new XivModelInfo() }; using (var br = new BinaryReaderBE(new MemoryStream(item))) { br.BaseStream.Seek(housingIndexOffset, SeekOrigin.Begin); var pictureIndex = br.ReadInt32(); if (pictureIndex == 0 || pictureIndex > (pictureDictionary.Count - 1)) { return; } br.BaseStream.Seek(itemNameDataOffset, SeekOrigin.Begin); var nameOffset = br.ReadInt16(); br.BaseStream.Seek(itemIconDataOffset, SeekOrigin.Begin); painting.IconNumber = br.ReadUInt16(); var gearNameOffset = itemDataLength + nameOffset; var gearNameLength = item.Length - gearNameOffset; br.BaseStream.Seek(gearNameOffset, SeekOrigin.Begin); var nameString = Encoding.UTF8.GetString(br.ReadBytes(gearNameLength)).Replace("\0", ""); painting.Name = new string(nameString.Where(c => !char.IsControl(c)).ToArray()); using (var br1 = new BinaryReaderBE(new MemoryStream(pictureDictionary[pictureIndex]))) { br1.BaseStream.Seek(iconNumberOffset, SeekOrigin.Begin); painting.ModelInfo.PrimaryID = br1.ReadInt32(); } } if (!painting.Name.Equals(string.Empty) && (painting.Name.IndexOf("painting", System.StringComparison.OrdinalIgnoreCase) >= 0)) { lock (paintingsLock) { furnitureList.Add(painting); } } })); furnitureList.Sort(); return(furnitureList); }
public void Load(string filename) { BinaryReaderBE reader = new BinaryReaderBE(File.Open(filename, FileMode.Open)); try { // is it MacBinary? int fork_start = 0; if (MacBinaryHeader(reader.ReadBytes(128))) { fork_start = 128; } reader.BaseStream.Seek(fork_start, SeekOrigin.Begin); // read the header version = reader.ReadInt16(); DataVersion = reader.ReadInt16(); Filename = reader.ReadMacString(maxFilename); checksum = reader.ReadUInt32(); directoryOffset = reader.ReadInt32(); short wadCount = reader.ReadInt16(); applicationSpecificDirectoryDataSize = reader.ReadInt16(); entryHeaderSize = reader.ReadInt16(); directoryEntryBaseSize = reader.ReadInt16(); // sanity check the map if (Version < 2 || DataVersion < 1 || entryHeaderSize != 16 || directoryEntryBaseSize != 10) { throw new BadMapException("Only Marathon 2 and higher maps are supported"); } ParentChecksum = reader.ReadUInt32(); reader.ReadBytes(2 * 20); // unused // load the directory reader.BaseStream.Seek(directoryOffset + fork_start, SeekOrigin.Begin); for (int i = 0; i < wadCount; ++i) { DirectoryEntry entry = new DirectoryEntry(); entry.LoadEntry(reader); if (applicationSpecificDirectoryDataSize == DirectoryEntry.DataSize) { entry.LoadData(reader); } else { reader.ReadBytes(applicationSpecificDirectoryDataSize); } Directory[entry.Index] = entry; } // load all the wads(!) foreach (KeyValuePair <int, DirectoryEntry> kvp in Directory) { reader.BaseStream.Seek(kvp.Value.Offset + fork_start, SeekOrigin.Begin); kvp.Value.LoadChunks(reader); } if (applicationSpecificDirectoryDataSize != DirectoryEntry.DataSize) { foreach (var kvp in Directory) { if (kvp.Value.Chunks.ContainsKey(MapInfo.Tag)) { MapInfo info = new MapInfo(); BinaryReaderBE chunkReader = new BinaryReaderBE(new MemoryStream(kvp.Value.Chunks[MapInfo.Tag])); info.Load(chunkReader); kvp.Value.MissionFlags = info.MissionFlags; kvp.Value.EnvironmentFlags = info.EnvironmentFlags; kvp.Value.EntryPointFlags = info.EntryPointFlags; kvp.Value.LevelName = info.Name; } } } } finally { reader.Close(); } }
/// <summary> /// Gets the list of indoor furniture /// </summary> /// <remarks> /// Housing items can be obtained one of two ways /// One: checking the housingfurniture exd for the item index, and going to that item to grab the data /// Two: iterating through the entire item list seeing if the item contains an index to a housing item (offset 112, 4 bytes) /// This method does option one /// </remarks> /// <returns>A list of XivFurniture objects containing indoor furniture item info</returns> private async Task <List <XivFurniture> > GetIndoorFurniture() { var indoorLock = new object(); // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch const int itemIndexOffset = 10; const int modelNumberOffset = 12; const int itemCategoryOffset = 14; const int itemNameDataOffset = 14; int itemDataLength = 168; const int itemIconDataOffset = 136; if (_xivLanguage == XivLanguage.Korean) { itemDataLength = 160; } else if (_xivLanguage == XivLanguage.Chinese) { itemDataLength = 160; } var ex = new Ex(_gameDirectory, _xivLanguage); var housingDictionary = await ex.ReadExData(XivEx.housingfurniture); var itemDictionary = await ex.ReadExData(XivEx.item); var furnitureList = new List <XivFurniture>(); await Task.Run(() => Parallel.ForEach(housingDictionary.Values, (housingItem) => { try { var item = new XivFurniture { PrimaryCategory = XivStrings.Housing, SecondaryCategory = XivStrings.Furniture_Indoor, ModelInfo = new XivModelInfo() }; using (var br = new BinaryReaderBE(new MemoryStream(housingItem))) { br.BaseStream.Seek(itemIndexOffset, SeekOrigin.Begin); var itemIndex = br.ReadUInt16(); br.BaseStream.Seek(modelNumberOffset, SeekOrigin.Begin); item.ModelInfo.PrimaryID = br.ReadInt16(); br.BaseStream.Seek(itemCategoryOffset, SeekOrigin.Begin); var housingCategory = br.ReadByte(); using (var br1 = new BinaryReaderBE(new MemoryStream(itemDictionary[itemIndex]))) { br1.BaseStream.Seek(itemNameDataOffset, SeekOrigin.Begin); var nameOffset = br1.ReadInt16(); br1.BaseStream.Seek(itemIconDataOffset, SeekOrigin.Begin); item.IconNumber = br1.ReadUInt16(); var gearNameOffset = itemDataLength + nameOffset; var gearNameLength = itemDictionary[itemIndex].Length - gearNameOffset; br1.BaseStream.Seek(gearNameOffset, SeekOrigin.Begin); var nameString = Encoding.UTF8.GetString(br1.ReadBytes(gearNameLength)).Replace("\0", ""); item.Name = new string(nameString.Where(c => !char.IsControl(c)).ToArray()); } } if (!item.Name.Equals(string.Empty)) { lock (indoorLock) { furnitureList.Add(item); } } } catch (Exception ex) { throw; } })); furnitureList.Sort(); return(furnitureList); }
public void Load(BinaryReaderBE reader) { ItemType = reader.ReadInt16(); PowerupType = reader.ReadInt16(); WeaponClass = reader.ReadInt16(); Flags = reader.ReadInt16(); FiringLightIntensity = reader.ReadFixed(); FiringIntensityDecayTicks = reader.ReadInt16(); IdleHeight = reader.ReadFixed(); BobAmplitude = reader.ReadFixed(); KickHeight = reader.ReadFixed(); ReloadHeight = reader.ReadFixed(); IdleWidth = reader.ReadFixed(); HorizontalAmplitude = reader.ReadFixed(); Collection = reader.ReadInt16(); IdleShape = reader.ReadInt16(); FiringShape = reader.ReadInt16(); ReloadingShape = reader.ReadInt16(); Unused = reader.ReadInt16(); ChargingShape = reader.ReadInt16(); ChargedShape = reader.ReadInt16(); ReadyTicks = reader.ReadInt16(); AwaitReloadTicks = reader.ReadInt16(); LoadingTicks = reader.ReadInt16(); FinishLoadingTicks = reader.ReadInt16(); PowerupTicks = reader.ReadInt16(); for (int i = 0; i < 2; ++i) { Triggers[i] = new TriggerDefinition(); Triggers[i].Load(reader); } }
/// <summary> /// Reads and parses the ExHeader file /// </summary> /// <param name="exFile">The Ex file to use.</param> private async Task ReadExHeader(XivEx exFile) { OffsetTypeDict = new Dictionary <int, int>(); PageList = new List <int>(); LanguageList = new List <int>(); var exdFolderHash = HashGenerator.GetHash("exd"); var exdFileHash = HashGenerator.GetHash(exFile + ExhExtension); var offset = await _index.GetDataOffset(exdFolderHash, exdFileHash, XivDataFile._0A_Exd); if (offset == 0) { throw new Exception($"Could not find offset for exd/{exFile}{ExhExtension}"); } var exhData = await _dat.GetType2Data(offset, XivDataFile._0A_Exd); await Task.Run(() => { // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(exhData))) { var signature = br.ReadInt32(); var version = br.ReadInt16(); var dataSetChunk = br.ReadInt16(); var dataSetCount = br.ReadInt16(); var pageTableCount = br.ReadInt16(); var langTableCount = br.ReadInt16(); var unknown = br.ReadInt16(); var unknown1 = br.ReadInt32(); var entryCount = br.ReadInt32(); br.ReadBytes(8); for (var i = 0; i < dataSetCount; i++) { var dataType = br.ReadInt16(); var dataOffset = br.ReadInt16(); if (!OffsetTypeDict.ContainsKey(dataOffset)) { OffsetTypeDict.Add(dataOffset, dataType); } } for (var i = 0; i < pageTableCount; i++) { var pageNumber = br.ReadInt32(); var pageSize = br.ReadInt32(); PageList.Add(pageNumber); } for (var i = 0; i < langTableCount; i++) { var langCode = br.ReadInt16(); if (langCode != 0) { LanguageList.Add(langCode); } } } }); }
public void Load(BinaryReaderBE reader) { Type = (PolygonType)reader.ReadInt16(); Flags = reader.ReadUInt16(); Permutation = reader.ReadInt16(); VertexCount = reader.ReadUInt16(); for (int i = 0; i < MaxVertexCount; ++i) { EndpointIndexes[i] = reader.ReadInt16(); } for (int i = 0; i < MaxVertexCount; ++i) { LineIndexes[i] = reader.ReadInt16(); } FloorTexture = (ShapeDescriptor)reader.ReadUInt16(); CeilingTexture = (ShapeDescriptor)reader.ReadUInt16(); FloorHeight = reader.ReadInt16(); CeilingHeight = reader.ReadInt16(); FloorLight = reader.ReadInt16(); CeilingLight = reader.ReadInt16(); reader.ReadInt32(); // area FirstObjectIndex = reader.ReadInt16(); reader.ReadInt16(); // first_exclusion_zone_index reader.ReadInt16(); // line_exclusion_zone_count reader.ReadInt16(); // point_exclusion_zone_count FloorTransferMode = reader.ReadInt16(); CeilingTransferMode = reader.ReadInt16(); for (int i = 0; i < MaxVertexCount; ++i) { AdjacentPolygonIndexes[i] = reader.ReadInt16(); } reader.ReadInt16(); // first_neighbor_index reader.ReadInt16(); // neighbor_count reader.ReadInt16(); // center.x reader.ReadInt16(); // center.y for (int i = 0; i < SideIndexes.Length; ++i) { SideIndexes[i] = reader.ReadInt16(); } FloorOrigin.Load(reader); CeilingOrigin.Load(reader); MediaIndex = reader.ReadInt16(); MediaLight = reader.ReadInt16(); reader.ReadInt16(); // sound_source_indexes AmbientSound = reader.ReadInt16(); RandomSound = reader.ReadInt16(); reader.BaseStream.Seek(2, SeekOrigin.Current); }
// private short nameLen; public void Load(BinaryReaderBE reader) { reader.ReadBytes(1); // reader.ReadBytes(1); Type = reader.ReadInt16(); // reader.ReadBytes(1); Flags = reader.ReadUInt16(); // long position = reader.BaseStream.Position; // position += 1;//??? // reader.BaseStream.Seek(position, SeekOrigin.Begin); // reader.ReadBytes(1); Name = reader.ReadMacString(33); NoOfViews = reader.ReadInt16(); FramesPerView = reader.ReadInt16(); TickePerFrame = reader.ReadInt16(); KeyFrame = reader.ReadInt16(); TrasferMode = reader.ReadInt16(); TransferModePeriod = reader.ReadInt16(); FirstFrameSound = reader.ReadInt16(); KeyFrameSound = reader.ReadInt16(); LastFrameSound = reader.ReadInt16(); PixelsToWorld = reader.ReadInt16(); LoopFrame = reader.ReadInt16(); // long position = reader.BaseStream.Position; // position += 28;//??? // reader.BaseStream.Seek(position, SeekOrigin.Begin); reader.ReadBytes(28); short nov = NoOfViews; int idxCount = getRealViewCount(nov) * FramesPerView; FrameIndexes = new List <int>(); for (int i = 0; i < idxCount; i++) { short frameIndex = reader.ReadInt16(); FrameIndexes.Add(frameIndex); } }
/// <summary> /// A getter for available gear in the Item exd files /// </summary> /// <returns>A list containing XivGear data</returns> public async Task <List <XivGear> > GetGearList() { // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch const int modelDataCheckOffset = 30; const int dataLength = 160; const int nameDataOffset = 14; const int modelDataOffset = 24; const int iconDataOffset = 136; const int slotDataOffset = 154; var xivGearList = new List <XivGear>(); xivGearList.AddRange(GetMissingGear()); var ex = new Ex(_gameDirectory, _xivLanguage); var itemDictionary = await ex.ReadExData(XivEx.item); // Loops through all the items in the item exd files // Item files start at 0 and increment by 500 for each new file // Item_0, Item_500, Item_1000, etc. await Task.Run(() => Parallel.ForEach(itemDictionary, (item) => { // This checks whether there is any model data present in the current item if (item.Value[modelDataCheckOffset] <= 0 && item.Value[modelDataCheckOffset + 1] <= 0) { return; } // Gear can have 2 separate models (MNK weapons for example) var primaryMi = new XivModelInfo(); var secondaryMi = new XivModelInfo(); var xivGear = new XivGear { Category = XivStrings.Gear, ModelInfo = primaryMi, SecondaryModelInfo = secondaryMi }; /* Used to determine if the given model is a weapon * This is important because the data is formatted differently * The model data is a 16 byte section separated into two 8 byte parts (primary model, secondary model) * Format is 8 bytes in length with 2 bytes per data point [short, short, short, short] * Gear: primary model [blank, blank, variant, ID] nothing in secondary model * Weapon: primary model [blank, variant, body, ID] secondary model [blank, variant, body, ID] */ var isWeapon = false; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(item.Value))) { br.BaseStream.Seek(nameDataOffset, SeekOrigin.Begin); var nameOffset = br.ReadInt16(); // Model Data br.BaseStream.Seek(modelDataOffset, SeekOrigin.Begin); // Primary Model Key primaryMi.ModelKey = Quad.Read(br.ReadBytes(8), 0); br.BaseStream.Seek(-8, SeekOrigin.Current); // Primary Blank primaryMi.Unused = br.ReadInt16(); // Primary Variant for weapon, blank otherwise var weaponVariant = br.ReadInt16(); if (weaponVariant != 0) { primaryMi.Variant = weaponVariant; isWeapon = true; } // Primary Body if weapon, Variant otherwise if (isWeapon) { primaryMi.Body = br.ReadInt16(); } else { primaryMi.Variant = br.ReadInt16(); } // Primary Model ID primaryMi.ModelID = br.ReadInt16(); // Secondary Model Key isWeapon = false; secondaryMi.ModelKey = Quad.Read(br.ReadBytes(8), 0); br.BaseStream.Seek(-8, SeekOrigin.Current); // Secondary Blank secondaryMi.Unused = br.ReadInt16(); // Secondary Variant for weapon, blank otherwise weaponVariant = br.ReadInt16(); if (weaponVariant != 0) { secondaryMi.Variant = weaponVariant; isWeapon = true; } // Secondary Body if weapon, Variant otherwise if (isWeapon) { secondaryMi.Body = br.ReadInt16(); } else { secondaryMi.Variant = br.ReadInt16(); } // Secondary Model ID secondaryMi.ModelID = br.ReadInt16(); // Icon br.BaseStream.Seek(iconDataOffset, SeekOrigin.Begin); xivGear.IconNumber = br.ReadUInt16(); // Gear Slot/Category br.BaseStream.Seek(slotDataOffset, SeekOrigin.Begin); int slotNum = br.ReadByte(); // Waist items do not have texture or model data if (slotNum == 6) { return; } xivGear.EquipSlotCategory = slotNum; xivGear.ItemCategory = _slotNameDictionary.ContainsKey(slotNum) ? _slotNameDictionary[slotNum] : "Unknown"; // Gear Name var gearNameOffset = dataLength + nameOffset; var gearNameLength = item.Value.Length - gearNameOffset; br.BaseStream.Seek(gearNameOffset, SeekOrigin.Begin); var nameString = Encoding.UTF8.GetString(br.ReadBytes(gearNameLength)).Replace("\0", ""); xivGear.Name = new string(nameString.Where(c => !char.IsControl(c)).ToArray()); lock (_gearLock) { xivGearList.Add(xivGear); } } })); xivGearList.Sort(); return(xivGearList); }
/// <summary> /// A getter for available gear in the Item exd files /// </summary> /// <returns>A list containing XivGear data</returns> public async Task <List <XivGear> > GetUnCachedGearList() { // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch const int modelDataCheckOffset = 30; int dataLength = DataLengthByPatch["5.5"]; const int nameDataOffset = 14; const int modelDataOffset = 24; const int iconDataOffset = 136; int slotDataOffset = SlotDataOffsetByPatch["5.5"]; if (_xivLanguage == XivLanguage.Korean) { dataLength = DataLengthByPatch["5.5"]; slotDataOffset = SlotDataOffsetByPatch["5.5"]; } else if (_xivLanguage == XivLanguage.Chinese) { dataLength = DataLengthByPatch["5.5"]; slotDataOffset = SlotDataOffsetByPatch["5.5"]; } var xivGearList = new List <XivGear>(); xivGearList.AddRange(GetMissingGear()); var ex = new Ex(_gameDirectory, _xivLanguage); var itemDictionary = await ex.ReadExData(XivEx.item); // Loops through all the items in the item exd files // Item files start at 0 and increment by 500 for each new file // Item_0, Item_500, Item_1000, etc. await Task.Run(() => Parallel.ForEach(itemDictionary, (item) => { try { // This checks whether there is any model data present in the current item if (item.Value[modelDataCheckOffset] <= 0 && item.Value[modelDataCheckOffset + 1] <= 0) { return; } var primaryMi = new XivGearModelInfo(); var secondaryMi = new XivGearModelInfo(); var hasSecondary = false; var xivGear = new XivGear { ExdID = item.Key, PrimaryCategory = XivStrings.Gear, ModelInfo = primaryMi, }; /* Used to determine if the given model is a weapon * This is important because the data is formatted differently * The model data is a 16 byte section separated into two 8 byte parts (primary model, secondary model) * Format is 8 bytes in length with 2 bytes per data point [short, short, short, short] * Gear: primary model [blank, blank, variant, ID] nothing in secondary model * Weapon: primary model [blank, variant, body, ID] secondary model [blank, variant, body, ID] */ var isWeapon = false; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(item.Value))) { br.BaseStream.Seek(nameDataOffset, SeekOrigin.Begin); var nameOffset = br.ReadInt16(); // Model Data br.BaseStream.Seek(modelDataOffset, SeekOrigin.Begin); // Primary Model Key primaryMi.ModelKey = Quad.Read(br.ReadBytes(8), 0); br.BaseStream.Seek(-8, SeekOrigin.Current); // Primary Blank var unused = br.ReadInt16(); // Primary Variant for weapon, blank otherwise var weaponVariant = br.ReadInt16(); if (weaponVariant != 0) { primaryMi.ImcSubsetID = weaponVariant; primaryMi.IsWeapon = true; isWeapon = true; } // Primary Body if weapon, Variant otherwise if (isWeapon) { primaryMi.SecondaryID = br.ReadInt16(); } else { primaryMi.ImcSubsetID = br.ReadInt16(); } // Primary Model ID primaryMi.PrimaryID = br.ReadInt16(); // Secondary Model Key isWeapon = false; secondaryMi.ModelKey = Quad.Read(br.ReadBytes(8), 0); br.BaseStream.Seek(-8, SeekOrigin.Current); // Secondary Blank var unused2 = br.ReadInt16(); // Secondary Variant for weapon, blank otherwise weaponVariant = br.ReadInt16(); if (weaponVariant != 0) { secondaryMi.ImcSubsetID = weaponVariant; secondaryMi.IsWeapon = true; isWeapon = true; } // Secondary Body if weapon, Variant otherwise if (isWeapon) { secondaryMi.SecondaryID = br.ReadInt16(); } else { secondaryMi.ImcSubsetID = br.ReadInt16(); } // Secondary Model ID secondaryMi.PrimaryID = br.ReadInt16(); // Icon br.BaseStream.Seek(iconDataOffset, SeekOrigin.Begin); xivGear.IconNumber = br.ReadUInt16(); // Gear Slot/Category br.BaseStream.Seek(slotDataOffset, SeekOrigin.Begin); int slotNum = br.ReadByte(); // Waist items do not have texture or model data if (slotNum == 6) { return; } xivGear.EquipSlotCategory = slotNum; xivGear.SecondaryCategory = _slotNameDictionary.ContainsKey(slotNum) ? _slotNameDictionary[slotNum] : "Unknown"; // Gear Name var gearNameOffset = dataLength + nameOffset; var gearNameLength = item.Value.Length - gearNameOffset; br.BaseStream.Seek(gearNameOffset, SeekOrigin.Begin); var nameString = Encoding.UTF8.GetString(br.ReadBytes(gearNameLength)).Replace("\0", ""); xivGear.Name = new string(nameString.Where(c => !char.IsControl(c)).ToArray()); xivGear.Name = xivGear.Name.Trim(); // If we have a secondary model XivGear secondaryItem = null; if (secondaryMi.PrimaryID != 0) { // Make a new item for it. secondaryItem = (XivGear)xivGear.Clone(); secondaryItem.ModelInfo = secondaryMi; xivGear.Name += " - " + XivStrings.Main_Hand; secondaryItem.Name += " - " + XivStrings.Off_Hand; xivGear.PairedItem = secondaryItem; secondaryItem.PairedItem = xivGear; xivGear.SecondaryCategory = XivStrings.Dual_Wield; secondaryItem.SecondaryCategory = XivStrings.Dual_Wield; } // Rings if (slotNum == 12) { // Make this the Right ring, and create the Left Ring entry. secondaryItem = (XivGear)xivGear.Clone(); xivGear.Name += " - " + XivStrings.Right; secondaryItem.Name += " - " + XivStrings.Left; xivGear.PairedItem = secondaryItem; secondaryItem.PairedItem = xivGear; } lock (_gearLock) { xivGearList.Add(xivGear); if (secondaryItem != null) { xivGearList.Add(secondaryItem); } } } } catch (Exception ex) { throw; } })); xivGearList.Sort(); return(xivGearList); }
public void Load(BinaryReaderBE reader) { Flags = reader.ReadUInt16(); MinimumLightIntensity = reader.ReadFixed(); BitmapIndex = reader.ReadInt16(); OriginX = reader.ReadInt16(); OriginY = reader.ReadInt16(); KeyX = reader.ReadInt16(); KeyY = reader.ReadInt16(); WorldLeft = reader.ReadInt16(); WorldRight = reader.ReadInt16(); WorldTop = reader.ReadInt16(); WorldBottom = reader.ReadInt16(); WorldX0 = reader.ReadInt16(); WorldY0 = reader.ReadInt16(); Unused = new short[4]; for (int i = 0; i < Unused.Length; i++) { Unused[i] = reader.ReadInt16(); } }