private void _WriteStat(BitBuffer bitBuffer, UnitObjectStats statBlock, Stat stat) { /***** Stat Block ***** * if (Context == 1) * { * RowIndex 11 RowIndex to Stats table - used in MP context. * } * else * { * Code 16 Code from Stats excel table. * * ParamsCount 2 Count of following. * { * Exists 1 Simple bool test. * { * ParamBitCount 6 Number of bits used in file. * * ParamOperationsFlags 2 Operations to be done to param value * if (ParamOperationsFlags & 0x01) * { * ParamShift 3 Not seen used - but is in ASM. * } * if (ParamOperationsFlags & 0x02) * { * ParamIsOffset 1 Param is offset - unknown usage. * } * * NoTableCode 1 Bool type. * if (!NoTableCode) * { * ParamTableCode 16 Like StatCode, allows param value to refer to an excel table. * } * } * } * * BitCount 6 Number of bits used in file for stat value. * * ValueOperationsFlags 3 Operations to be performed on stat value. * if (otherAttributeFlag & 0x01) * { * ValueShift 4 Value shift - unknown usage. Probably used server-side to allow for greater ranges. * } * if (otherAttributeFlag & 0x02) * { * ValueOffset 12 Value if offset. Real value: Value -= ValueOffset; * } * if (otherAttributeFlag & 0x04) * { * ValueIsOffset 1 Not to be confused with ValueOffset - IsOffset usage unknown (similar to ParamIsOffset) * } * * NoValueTableCode 2 ASM only considered 0x00 - any other value and ValueTableCode is not read in. * if (!NoValueTableCode) * { * ValueTableCode 16 Allows value to refer to an excel table. * } * * } // end if (Context == 1) * * * HasMultipleValues 1 Bool type. * { * ValueCount 10 Number of times to read in stat values. * } * * for (ValueCount) If HasMultipleValues == false, then obviously we still want to read * { in at least once... So really it's like a do {} while() chunk. * for (ParamsCount) * { * ParamValue ParamBitCount The extra attribute for the applicable value below. * } * * StatValue BitCount The actual stat value. * } */ StatsRow statData = stat.StatRow; int valueBitCount; int[] paramsBitCounts = new int[MaxParams]; if (statBlock.Context == StatContext.UseRows) { valueBitCount = statData.valbits; paramsBitCounts[0] = statData.param1Bits; // todo: this could be an issue if we have to write a value greater than the bits can handle paramsBitCounts[1] = statData.param2Bits; paramsBitCounts[2] = statData.param3Bits; paramsBitCounts[3] = statData.param4Bits; int rowIndex = _fileManager.GetStatRowIndexFromCode((short) statData.code); if (rowIndex == -1) throw new Exceptions.UnitObjectException("Error: Stat row index not found for Stat = " + statData); bitBuffer.WriteBits(rowIndex, 11); if (statData.ParamCount > 0) bitBuffer.WriteBool(true); if (statData.ParamCount > 1) bitBuffer.WriteBool(true); if (statData.ParamCount > 2) bitBuffer.WriteBool(true); if (statData.ParamCount > 3) bitBuffer.WriteBool(true); } else { valueBitCount = (statData.valTable == -1) ? statData.valbits : 32; // on sp side - the bit count is equal to the bit count of the code field (32 for int, 16 for short, etc), but this will do paramsBitCounts[0] = (statData.param1Table == -1) ? statData.param1Bits : 32; // todo: this could be an issue if we have to write a value greater than the bits can handle paramsBitCounts[1] = (statData.param2Table == -1) ? statData.param2Bits : 32; paramsBitCounts[2] = (statData.param3Table == -1) ? statData.param3Bits : 32; paramsBitCounts[3] = (statData.param4Table == -1) ? statData.param4Bits : 32; bitBuffer.WriteUInt16((uint)statData.code); bitBuffer.WriteBits(statData.ParamCount, 2); if (statData.ParamCount > 0) _WriteStatParamData(bitBuffer, paramsBitCounts[0], statData.param1Shift, statData.param1Offs != 0, stat.Param1TableCode); if (statData.ParamCount > 1) _WriteStatParamData(bitBuffer, paramsBitCounts[1], statData.param2Shift, statData.param2Offs != 0, stat.Param2TableCode); if (statData.ParamCount > 2) _WriteStatParamData(bitBuffer, paramsBitCounts[2], statData.param3Shift, statData.param3Offs != 0, stat.Param3TableCode); if (statData.ParamCount > 3) _WriteStatParamData(bitBuffer, paramsBitCounts[3], statData.param4Shift, statData.param4Offs != 0, stat.Param4TableCode); bitBuffer.WriteBits(valueBitCount, 6); int valueOperationsFlags = 0; if (stat.StatRow.valShift > 0) valueOperationsFlags |= 0x01; if (stat.StatRow.valOffs > 0) valueOperationsFlags |= 0x02; if (stat.StatRow.offset > 0) valueOperationsFlags |= 0x04; bitBuffer.WriteBits(valueOperationsFlags, 3); if ((valueOperationsFlags & 0x01) != 0) { bitBuffer.WriteBits(stat.StatRow.valShift, 4); } if ((valueOperationsFlags & 0x02) != 0) { bitBuffer.WriteBits(stat.StatRow.valOffs, 12); } if ((valueOperationsFlags & 0x04) != 0) { bitBuffer.WriteBool(true); } int noValueTableCode = (stat.ValueTable != null) ? 0 : 1; bitBuffer.WriteBits(noValueTableCode, 2); if (stat.ValueTable != null) { bitBuffer.WriteUInt16((uint)stat.ValueTableCode); } } int valueCount = stat.Values.Count; bool hasMultipleValues = (valueCount > 1); bitBuffer.WriteBool(hasMultipleValues); if (hasMultipleValues) { int valueCountBits = (statBlock._version <= 7) ? 7 : 10; bitBuffer.WriteBits(valueCount, valueCountBits); } foreach (Stat.StatValue statValue in stat.Values) { if (statData.ParamCount >= 1) _WriteStatValue(bitBuffer, statValue.Param1, statValue.Param1Row, stat.Param1Table, paramsBitCounts[0], statBlock.Context); if (statData.ParamCount >= 2) _WriteStatValue(bitBuffer, statValue.Param2, statValue.Param2Row, stat.Param2Table, paramsBitCounts[1], statBlock.Context); if (statData.ParamCount >= 3) _WriteStatValue(bitBuffer, statValue.Param3, statValue.Param3Row, stat.Param3Table, paramsBitCounts[2], statBlock.Context); if (statData.ParamCount >= 4) _WriteStatValue(bitBuffer, statValue.Param4, statValue.Param4Row, stat.Param4Table, paramsBitCounts[3], statBlock.Context); int valueOffset = (stat.StatRow.valOffs + stat.StatRow.offset); int valueShift = (stat.StatRow.valShift - stat.StatRow.shift); statValue.Value += valueOffset; statValue.Value >>= valueShift; _WriteStatValue(bitBuffer, statValue.Value, statValue.ValueRow, stat.ValueTable, valueBitCount, statBlock.Context); } }
public void WriteStats(BitBuffer bitBuffer, UnitObjectStats stats, bool writeNameCount = false) { /***** Stat Block Header ***** * Version 16 Stat block header - Must be 0x000A. * Context 3 Use 0 for Code usage, 1 for RowIndex usage, 2 for... ? * * StatSelectorCount 6 Not sure of use - but uses StatSelector table * { * Code 16 Code from StatSelector table (if Context != 1) * RowIndex 5 RowIndex from StatSelector table (if Context == 1) * * StatCount 16 Count of following stats. * { * STATS See WriteStat(). * } * } * * StatCount 16 Count of following stats. * { * STATS See WriteStat(). * } * * // todo: update me (same StatSelector stuff from above) * if (WriteNameCount) This is TRUE by default. Set to FALSE when writing a stat block * { from the below name stat block chunk. * NameCount 8 I think this has something to do with item names. * { * Code 16 Code from StatSelector table (if Context != 1) * RowIndex 5 RowIndex from StatSelector table (if Context == 1) * * STAT BLOCK See WriteStatBlock(). * } * } */ bitBuffer.WriteBits(stats._version, 16); bitBuffer.WriteBits((int)stats.Context, 3); bitBuffer.WriteBits(stats.StatSelectors.Count, 6); foreach (StatSelector statSelector in stats.StatSelectors) { if (stats.Context == StatContext.UseRows) { bitBuffer.WriteBits(statSelector.RowIndex, 5); } else { bitBuffer.WriteUInt16(statSelector.Code); } bitBuffer.WriteBits(statSelector.Stats.Count, 16); foreach (Stat stat in statSelector.Stats) { _WriteStat(bitBuffer, stats, stat); } } bitBuffer.WriteBits(stats.Stats.Count, 16); foreach (Stat stat in stats.Stats.Values.OrderBy(stat => stat.Code)) { _WriteStat(bitBuffer, stats, stat); } if (!writeNameCount) return; bitBuffer.WriteBits(stats.Names.Count, 8); foreach (StatName statName in stats.Names) { bitBuffer.WriteBits(statName.Unknown1, 16); WriteStats(bitBuffer, statName.Stats, false); } }
private static void _WriteStatParamData(BitBuffer bitBuffer, int bitCount, int paramShift, bool paramIsOffset, Xls.TableCodes tableCode) { if (bitCount <= 0) { bitBuffer.WriteBool(false); return; } bitBuffer.WriteBool(true); bitBuffer.WriteBits(bitCount, 6); int paramOperationsFlags = 0; if (paramShift > 0) paramOperationsFlags |= 0x01; if (paramIsOffset) paramOperationsFlags |= 0x02; bitBuffer.WriteBits(paramOperationsFlags, 2); if ((paramOperationsFlags & 0x01) != 0) { bitBuffer.WriteBits(paramShift, 3); } if ((paramOperationsFlags & 0x02) != 0) { bitBuffer.WriteBool(paramIsOffset); } bool hasTableCode = (tableCode != Xls.TableCodes.Null && tableCode != Xls.TableCodes.None); bitBuffer.WriteBool(!hasTableCode); if (hasTableCode) { bitBuffer.WriteUInt16((uint)tableCode); } }
private void _WriteStatValue(BitBuffer bitBuffer, int value, Object valueRow, ExcelFile valueTable, int bitCount, StatContext statContext) { if (bitCount <= 0) return; if (valueTable == null) { bitBuffer.WriteBits(value, bitCount); return; } if (valueRow == null) { bitBuffer.WriteBits(0, bitCount); return; } if (statContext == StatContext.UseRows) { int rowIndex = valueTable.Rows.IndexOf(valueRow); bitBuffer.WriteBits(rowIndex, bitCount); } else { int code = _fileManager.GetCodeFromRow(valueTable.TableCode, valueRow); bitBuffer.WriteBits(code, bitCount); } }