private static Stat.StatValue _CreateStatValue(StatsRow statsRow, int value, int[] paramValues) { Object valueRow = null; if (statsRow.ValueExcelTable != null && value >= 0 && value < statsRow.ValueExcelTable.Rows.Count) { valueRow = statsRow.ValueExcelTable.Rows[value]; } Stat.StatValue statValue = new Stat.StatValue { Value = value, ValueRow = valueRow }; if (paramValues == null || paramValues.Length == 0) return statValue; if (paramValues.Length >= 1) { statValue.Param1 = paramValues[0]; if ((statsRow.Param1ExcelTable != null && paramValues[0] >= 0 && paramValues[0] < statsRow.Param1ExcelTable.Rows.Count)) { statValue.Param1Row = statsRow.Param1ExcelTable.Rows[paramValues[0]]; } } if (paramValues.Length >= 2) { statValue.Param2 = paramValues[1]; if ((statsRow.Param2ExcelTable != null && paramValues[1] >= 0 && paramValues[1] < statsRow.Param2ExcelTable.Rows.Count)) { statValue.Param2Row = statsRow.Param2ExcelTable.Rows[paramValues[1]]; } } if (paramValues.Length >= 3) { statValue.Param3 = paramValues[2]; if ((statsRow.Param3ExcelTable != null && paramValues[2] >= 0 && paramValues[2] < statsRow.Param3ExcelTable.Rows.Count)) { statValue.Param3Row = statsRow.Param3ExcelTable.Rows[paramValues[2]]; } } if (paramValues.Length >= 4) { statValue.Param4 = paramValues[3]; if ((statsRow.Param4ExcelTable != null && paramValues[3] >= 0 && paramValues[3] < statsRow.Param4ExcelTable.Rows.Count)) { statValue.Param4Row = statsRow.Param4ExcelTable.Rows[paramValues[3]]; } } return statValue; }
private Stat _ReadStat(BitBuffer bitBuffer, UnitObjectStats statBlock) { Stat stat = new Stat(); int statIndex = statBlock.Stats.Count; int valueShift = 0; int valueOffset = 0; bool isOffset = false; StatsRow statData; int valueBitCount; int[] paramsBitCounts = new int[MaxParams]; if (statBlock.Context == StatContext.UseRows) { int rowIndex = bitBuffer.ReadBits(11); // todo: make this a static value - this bit count is determined by FileManager._GetTableRowBitMax() of the Stats row count statData = stat.StatRow = _fileManager.GetStatRowFromIndex(rowIndex); if (statData == null) throw new Exceptions.UnitObjectException(String.Format("Error stats[{0}].RowIndex = {1} not found.\nCannot have null stat - not known param count will break bit offset.", statIndex, rowIndex)); valueBitCount = statData.valbits; if (statData.ParamCount > 0 && bitBuffer.ReadBool()) paramsBitCounts[0] = statData.param1Bits; if (statData.ParamCount > 1 && bitBuffer.ReadBool()) paramsBitCounts[1] = statData.param2Bits; if (statData.ParamCount > 2 && bitBuffer.ReadBool()) paramsBitCounts[2] = statData.param3Bits; if (statData.ParamCount > 3 && bitBuffer.ReadBool()) paramsBitCounts[3] = statData.param4Bits; if (_debugOutputLoadingProgress) { Debug.WriteLine(String.Format("stats[{0}].Name = {1}, .Code = {2} (0x{3:X4}), .ParamCount = {4}", statIndex, stat.Name, stat.Code, (uint)stat.Code, statData.ParamCount)); Xls.TableCodes tableCode = (stat.ValueTable == null) ? Xls.TableCodes.Null : stat.ValueTable.TableCode; int noValueTableCode = (stat.ValueTable == null) ? 1 : 0; Debug.WriteLine(String.Format("stats[{0}].NoValueTableCode = {1}, .ValueTableCode = 0x{2:X4}, .ValueTable = {3}", statIndex, noValueTableCode, (uint)tableCode, tableCode)); if (statData.ParamCount >= 1) Debug.WriteLine(String.Format("stats[{0}].Param1.BitCount = {1}, .Table = {2}", statIndex, paramsBitCounts[0], stat.Param1TableCode)); if (statData.ParamCount >= 2) Debug.WriteLine(String.Format("stats[{0}].Param2.BitCount = {1}, .Table = {2}", statIndex, paramsBitCounts[1], stat.Param2TableCode)); if (statData.ParamCount >= 3) Debug.WriteLine(String.Format("stats[{0}].Param3.BitCount = {1}, .Table = {2}", statIndex, paramsBitCounts[2], stat.Param3TableCode)); if (statData.ParamCount >= 4) Debug.WriteLine(String.Format("stats[{0}].Param4.BitCount = {1}, .Table = {2}", statIndex, paramsBitCounts[3], stat.Param4TableCode)); } } else { ushort code = bitBuffer.ReadUInt16(); statData = stat.StatRow = _fileManager.GetStatRowFromCode((short)code); if (stat.StatRow == null) throw new Exceptions.UnitObjectException(String.Format("Error: stat.Code = {0} (0x{0:X4}) not found.\nCannot have null stat - not known param count will break bit offset.", code)); int paramsCount = bitBuffer.ReadBits(2); if (_debugOutputLoadingProgress) { Debug.WriteLine(String.Format("stats[{0}].Name = {1}, stat.Code = {2} (0x{3:X4}), stat.ParamCount = {4}", statIndex, stat.Name, code, (uint)code, paramsCount)); } if (paramsCount > statData.ParamCount) Debug.WriteLine(String.Format("Unexpected large params count of {0}. Expecting count <= {1}", paramsCount, statData.ParamCount)); for (int i = 0; i < paramsCount; i++) { bool exists = bitBuffer.ReadBool(); if (!exists) continue; paramsBitCounts[i] = bitBuffer.ReadBits(6); int paramOperationsFlags = bitBuffer.ReadBits(2); int paramShift = 0; bool paramIsOffset = false; if ((paramOperationsFlags & 0x01) != 0) { paramShift = bitBuffer.ReadBits(3); } if ((paramOperationsFlags & 0x02) != 0) { paramIsOffset = bitBuffer.ReadBool(); } bool hasTableCode = !bitBuffer.ReadBool(); Xls.TableCodes paramTableCode = Xls.TableCodes.Null; if (hasTableCode) { paramTableCode = (Xls.TableCodes)bitBuffer.ReadUInt16(); Xls.TableCodes expetedTableCode = Xls.TableCodes.Null; switch (i) { case 0: expetedTableCode = stat.Param1TableCode; break; case 1: expetedTableCode = stat.Param2TableCode; break; case 2: expetedTableCode = stat.Param3TableCode; break; case 3: expetedTableCode = stat.Param4TableCode; break; } if (expetedTableCode != paramTableCode) throw new Exceptions.UnitObjectException(String.Format("Unexpected param value table supplied. Expecting {0}, got {1}", expetedTableCode, paramTableCode)); } if (_debugOutputLoadingProgress) { Debug.WriteLine(String.Format("stats[{0}].Param{1}.BitCount = {2}, .ParamOperationsFlags = {3}, .ParamShift = {4}, .ParamIsOffset = {5}, .HasTableCode = {6}, .TableCode = {7}, .Table = {8}", statIndex, i, paramsBitCounts[i], paramOperationsFlags, paramShift, paramIsOffset, hasTableCode, (uint)paramTableCode, paramTableCode)); } } valueBitCount = bitBuffer.ReadBits(6); int valueOperationsFlags = bitBuffer.ReadBits(3); if ((valueOperationsFlags & 0x01) != 0) { valueShift = bitBuffer.ReadBits(4); // valShift } if ((valueOperationsFlags & 0x02) != 0) { valueOffset = bitBuffer.ReadBits(12); // valOffset } if ((valueOperationsFlags & 0x04) != 0) { isOffset = bitBuffer.ReadBool(); } if (_debugOutputLoadingProgress) { Debug.WriteLine(String.Format("stats[{0}].BitCount = {1}, .ValueOperationsFlags = {2}, .ValueShift = {3}, .ValueOffset = {4}, .IsOffset = {5}", statIndex, valueBitCount, valueOperationsFlags, valueShift, valueOffset, isOffset)); } int noValueTableCode = bitBuffer.ReadBits(2); Debug.Assert(noValueTableCode != 2); // never seen... seen in stats column in Monsters table Xls.TableCodes tableCode = Xls.TableCodes.Null; if (noValueTableCode == 0) { tableCode = (Xls.TableCodes)bitBuffer.ReadUInt16(); Xls.TableCodes expectedTableCode = stat.ValueTableCode; if (expectedTableCode != tableCode) throw new Exceptions.UnitObjectException(String.Format("Unexpected stat value table supplied. Expecting {0}, got {1}", expectedTableCode, tableCode)); } if (_debugOutputLoadingProgress) { Debug.WriteLine(String.Format("stats[{0}].NoValueTableCode = {1}, .ValueTableCode = 0x{2:X4}, .ValueTable = {3}", statIndex, noValueTableCode, (uint)tableCode, tableCode)); } } bool hasMultipleValues = bitBuffer.ReadBool(); int valueCount = 1; if (hasMultipleValues) { int valueCountBits = (statBlock._version <= 7) ? 8 : 10; valueCount = bitBuffer.ReadBits(valueCountBits); } if (_debugOutputLoadingProgress) { Debug.WriteLine(String.Format("stats[{0}].HasMultipleValues = {1}, .ValueCount = {2}", statIndex, hasMultipleValues, valueCount)); } for (int i = 0; i < valueCount; i++) { Stat.StatValue statValue = new Stat.StatValue(); _ReadStatValue(bitBuffer, paramsBitCounts[0], ref statValue.Param1, stat.Param1Table, ref statValue.Param1Row, statBlock.Context); _ReadStatValue(bitBuffer, paramsBitCounts[1], ref statValue.Param2, stat.Param2Table, ref statValue.Param2Row, statBlock.Context); _ReadStatValue(bitBuffer, paramsBitCounts[2], ref statValue.Param3, stat.Param3Table, ref statValue.Param3Row, statBlock.Context); _ReadStatValue(bitBuffer, paramsBitCounts[3], ref statValue.Param4, stat.Param4Table, ref statValue.Param4Row, statBlock.Context); _ReadStatValue(bitBuffer, valueBitCount, ref statValue.Value, stat.ValueTable, ref statValue.ValueRow, statBlock.Context); // this seems to work // todo: do this for writing stats if (valueOffset == 0) valueOffset = (stat.StatRow.valOffs + stat.StatRow.offset); if (valueShift == 0) valueShift = (stat.StatRow.valShift - stat.StatRow.shift); statValue.Value -= valueOffset; // not going to bother with this for now statValue.Value <<= valueShift; // not sure what this is for either - possibly server-side to increase accuracy/value range I guess - but values aren't saved with it... //if (value.IsOffset) statValue.Value--; // do this to *row index* though, not code - not sure about non-table relations values... stat.Values.Add(statValue); if (_debugOutputLoadingProgress) { if (paramsBitCounts[0] > 0) Debug.WriteLine(String.Format("stats[{0}].Param1 = {1}", statIndex, statValue.Param1)); if (paramsBitCounts[1] > 0) Debug.WriteLine(String.Format("stats[{0}].Param2 = {1}", statIndex, statValue.Param2)); if (paramsBitCounts[2] > 0) Debug.WriteLine(String.Format("stats[{0}].Param3 = {1}", statIndex, statValue.Param3)); if (paramsBitCounts[3] > 0) Debug.WriteLine(String.Format("stats[{0}].Param4 = {1}", statIndex, statValue.Param4)); Debug.WriteLine(String.Format("stats[{0}].Value = {1}", statIndex, statValue.Value)); } } return stat; }
public Stat SetStatAt(StatsRow statData, int index, int value, int? param1 = null, int? param2 = null, int? param3 = null, int? param4 = null) { return Stats.AddOrUpdate(statData.code, (code) => { int totalParams = 0; totalParams += (param1.HasValue ? 1 : 0); totalParams += (param2.HasValue ? 1 : 0); totalParams += (param3.HasValue ? 1 : 0); totalParams += (param4.HasValue ? 1 : 0); int[] paramValues = new int[totalParams]; if (param1.HasValue) paramValues.SetValue(param1, 0); if (param2.HasValue) paramValues.SetValue(param2, 1); if (param3.HasValue) paramValues.SetValue(param3, 2); if (param4.HasValue) paramValues.SetValue(param4, 3); return _AddStat(statData, value, paramValues); }, (code, stat) => { if (stat.Values.Count > index) return null; lock (stat.Values) { Stat.StatValue statValue; if (stat.Values.Count == index) { statValue = new Stat.StatValue(); stat.Values.Add(statValue); } else { statValue = stat.Values[index]; } statValue.Value = value; if (param1.HasValue) { statValue.Param1 = param1.Value; if ((statData.Param1ExcelTable != null && param1.Value >= 0 && param1.Value < statData.Param1ExcelTable.Rows.Count)) { statValue.Param1Row = statData.Param1ExcelTable.Rows[param1.Value]; } } if (param2.HasValue) { statValue.Param2 = param2.Value; if ((statData.Param2ExcelTable != null && param2.Value >= 0 && param2.Value < statData.Param2ExcelTable.Rows.Count)) { statValue.Param2Row = statData.Param2ExcelTable.Rows[param2.Value]; } } if (param3.HasValue) { statValue.Param3 = param3.Value; if ((statData.Param3ExcelTable != null && param3.Value >= 0 && param3.Value < statData.Param3ExcelTable.Rows.Count)) { statValue.Param3Row = statData.Param3ExcelTable.Rows[param3.Value]; } } if (param4.HasValue) { statValue.Param4 = param4.Value; if ((statData.Param4ExcelTable != null && param4.Value >= 0 && param4.Value < statData.Param4ExcelTable.Rows.Count)) { statValue.Param4Row = statData.Param4ExcelTable.Rows[param4.Value]; } } } return stat; } ); }