/// <summary> /// Writes an item property to the BitStream /// </summary> /// <param name="bs">Bitstream to write property to</param> /// <param name="property">Property to write</param> private void WriteItemProperty(BitStream bs, PropertyInfo property) { if (property.ID == 0x1ff) { bs.WriteReversed(property.ID, 9); return; } ItemStatCost statCost = ItemDefs.ItemStatCostsById[property.ID]; int fixedValue = property.Value + statCost.SaveAdd; if (!property.IsAdditionalProperty) { bs.WriteReversed(property.ID, 9); } bs.WriteReversed(fixedValue, statCost.SaveBits); if (statCost.SaveParamBits > 0) { bs.WriteReversed(property.ParamValue, statCost.SaveParamBits); } }
/// <summary> /// Converts specified item into item format for save file /// </summary> /// <returns>Byte representation of item for save file</returns> public byte[] GetItemBytes() { BitStream bs = new BitStream(); bs.WriteReversed('J', 8); bs.WriteReversed('M', 8); var ordered = dataEntries.OrderBy(n => n.Value.Index); foreach (var item in ordered) { if (item.Value.Value is string) { string value = item.Value.Value as string; if (item.Key == "ItemCode") { foreach (var ch in value) { bs.WriteReversed(ch, 8); } bs.WriteReversed(' ', 8); } else if (item.Key == "EarName" || item.Key == "PersonalizedName") { foreach (var ch in value) { bs.WriteReversed(ch, 7); } bs.WriteReversed(0, 7); } else { throw new Exception("Unknown string type in item data"); } } else if (item.Value.Value is ValueType) { // LAST key is the very last property added to the item data if (item.Key == "LAST") continue; TypeCode valueType = Type.GetTypeCode(item.Value.Value.GetType()); if (valueType == TypeCode.UInt32) { uint value = (uint)item.Value.Value; if (item.Key == "Defense") { value += (uint)ItemDefs.ItemStatCostsByName["armorclass"].SaveAdd; } else if (item.Key == "MaxDurability") { value += (uint)ItemDefs.ItemStatCostsByName["maxdurability"].SaveAdd; } else if (item.Key == "Durability") { value += (uint)ItemDefs.ItemStatCostsByName["durability"].SaveAdd; } bs.WriteReversed(value, item.Value.BitCount); } else if (valueType == TypeCode.Int32) { bs.WriteReversed((uint)((int)item.Value.Value), item.Value.BitCount); } else if (valueType == TypeCode.Boolean) { bs.Write((bool)item.Value.Value); } else { throw new Exception("Invalid ValueType!"); } } else { throw new Exception("Invalid data type in item dataEntries"); } } foreach (var item in properties) { WriteItemProperty(bs, item); } foreach (var item in propertiesSet) { WriteItemProperty(bs, item); } foreach (var item in propertiesRuneword) { WriteItemProperty(bs, item); } // Some simple items do have remaining data such as the soulstone if (IsSimpleItem) { //TODO: Enable renaming of ear and personlized names? if (remainingBytes != null) { bs.WriteReversed(remainingBytes); } if (dataEntries.ContainsKey("LAST")) { var lastEntry = dataEntries["LAST"]; bs.WriteReversed((uint)lastEntry.Value, lastEntry.BitCount); } } else { // Fill the last byte with 0 if it's not already full if ((bs.Position % 8) != 0) { int bitsToAdd = 8 - (int)(bs.Position % 8); if (bitsToAdd > 0) { bs.WriteReversed(0, bitsToAdd); } } } return bs.ToReversedByteArray(); }
/// <summary> /// Converts all stat data into raw data for save file /// </summary> /// <returns>Raw stat data ready for insertion into save file</returns> public byte[] GetStatBytes() { BitStream bits = new BitStream(); bits.WriteReversed('g', 8); bits.WriteReversed('f', 8); var sortedValues = from n in statValues where true orderby n.Key select n; foreach (var stat in sortedValues) { bits.WriteReversed(stat.Key, 9); int valShift = 0; int bitCount = ItemDefs.ItemStatCostsById[stat.Key].CSvBits; if (ItemDefs.ItemStatCostsById.ContainsKey(stat.Key)) { valShift = ItemDefs.ItemStatCostsById[stat.Key].ValShift; } bits.WriteReversed((uint)((stat.Value << valShift)), bitCount); } // Write termining stat index bits.WriteReversed(0x1ff, 9); // Add 0 padding to align to byte, if needed int remainingBitsForAlignment = 8 - (int)(bits.Position % 8); if (remainingBitsForAlignment > 0) { bits.WriteReversed(0, remainingBitsForAlignment); } return bits.ToReversedByteArray(); }