コード例 #1
0
ファイル: TestScripts.cs プロジェクト: khadoran/reanimator
        /// <summary>
        /// This function checks every row/col of every excel file, determining if it needs to be visible/public or not.
        /// Any element non-zero for all rows, needs to be public (or add new OutputAttribute for "const" values?)
        /// </summary>
        public static void ExcelValuesDeepScan()
        {
            FileManager fileManager = new FileManager(Config.HglDir);
            fileManager.ExtractAllExcel();

            Dictionary<uint, uint> rowTypeCounts = new Dictionary<uint, uint>();
            Dictionary<String, uint[]> outputMessages = new Dictionary<String, uint[]>();
            Dictionary<String, ObjectDelegator> objectDelegators = new Dictionary<String, ObjectDelegator>();
            foreach (PackFileEntry fileEntry in fileManager.FileEntries.Values)
            {
                if (!fileEntry.Name.EndsWith(ExcelFile.Extension)) continue;

                byte[] fileBytes = fileManager.GetFileBytes(fileEntry, true);
                Debug.Assert(fileBytes != null);

                ExcelFile excelFile = new ExcelFile(fileBytes, fileEntry.Path);
                if (excelFile.Attributes.IsEmpty) continue;

                Debug.WriteLine("Checking file: " + fileEntry.Path);

                uint structureId = excelFile.Attributes.StructureId;
                uint structureUseCount = 0;
                if (rowTypeCounts.TryGetValue(structureId, out structureUseCount))
                {
                    rowTypeCounts[structureId] = ++structureUseCount;
                }
                else
                {
                    rowTypeCounts.Add(structureId, 1);
                }

                ObjectDelegator excelDelegator;
                Type rowType = excelFile.Attributes.RowType;
                FieldInfo[] fieldInfos = rowType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                int rowCount = excelFile.Rows.Count;

                // create delegates
                if (!objectDelegators.TryGetValue(excelFile.StringId, out excelDelegator))
                {
                    excelDelegator = new ObjectDelegator(fieldInfos);
                    objectDelegators.Add(excelFile.StringId, excelDelegator);
                }

                // check by column, by row
                int col = -1;
                foreach (FieldInfo fieldInfo in fieldInfos)
                {
                    if (++col == 0) continue; // row header

                    ObjectDelegator.FieldGetValueDelegate getValue = excelDelegator.GetFieldGetDelegate(fieldInfo.Name);
                    ExcelFile.OutputAttribute outputAttribute = ExcelFile.GetExcelAttribute(fieldInfo);

                    bool isArray = false;
                    bool allEqual = true;
                    Object firstValue = null;
                    Array firstValueArray = null;
                    int arrayIndexFirstDifferent = -1;
                    int row = -1;
                    String message = null;
                    foreach (Object value in excelFile.Rows.Select(rowObject => getValue(rowObject)))
                    {
                        arrayIndexFirstDifferent = -1;
                        if (++row == 0)
                        {
                            if (fieldInfo.FieldType.BaseType == typeof(Array))
                            {
                                firstValueArray = (Array)value;
                                isArray = true;
                                IEnumerator enumerator = firstValueArray.GetEnumerator();
                                enumerator.MoveNext();
                                firstValue = enumerator.Current;
                            }
                            else
                            {
                                firstValue = value;
                            }
                            continue;
                        }

                        if (isArray)
                        {
                            Array objArray = (Array)value;
                            Debug.Assert(firstValueArray != null);

                            bool arrayEqual = true;
                            IEnumerator enumeratorFirst = firstValueArray.GetEnumerator();
                            IEnumerator enumeratorCurrent = objArray.GetEnumerator();
                            while (enumeratorFirst.MoveNext())
                            {
                                enumeratorCurrent.MoveNext();
                                arrayIndexFirstDifferent++;

                                Object objFirst = enumeratorFirst.Current;
                                Object objCurrent = enumeratorCurrent.Current;

                                if (firstValue == null) firstValue = objFirst;
                                if (objFirst.Equals(objCurrent)) continue;

                                arrayEqual = false;
                                break;
                            }

                            if (arrayEqual) continue;
                            allEqual = false;
                            break;
                        }

                        Debug.Assert(firstValue != null);
                        if (firstValue.Equals(value)) continue;
                        allEqual = false;
                        break;
                    }
                    Debug.Assert(firstValue != null);

                    Object constValue = null;
                    bool ignoreConstCheck = false;
                    if (outputAttribute != null)
                    {
                        constValue = outputAttribute.ConstantValue;
                        ignoreConstCheck = outputAttribute.DebugIgnoreConstantCheck;
                    }

                    if (fieldInfo.IsPrivate)
                    {
                        if (!allEqual)
                        {
                            message = String.Format("Warning: Private column (Type = {1}, StructureId = 0x{2}) \"{0}\" has per-row differing values",
                                fieldInfo.Name, fieldInfo.FieldType, structureId.ToString("X8")); // need to add structureId to ensure message is unique per structure type

                            if (isArray)
                            {
                                message += ", first index differing: " + arrayIndexFirstDifferent;
                            }
                        }
                        else // allEqual && IsPrivate
                        {
                            if (isArray)
                            {
                                if (fieldInfo.FieldType == typeof(Int32[]))
                                {
                                    if (firstValue.Equals((Int32)0)) continue;
                                }
                                else if (fieldInfo.FieldType == typeof(byte[]))
                                {
                                    if (firstValue.Equals((byte)0x00)) continue;
                                }
                                else
                                {
                                    Debug.Assert(false, "Unexpected Array Type: " + fieldInfo.FieldType);
                                }

                                if (outputAttribute != null && firstValue.Equals(outputAttribute.ConstantValue)) continue;

                                message = String.Format("Warning: Private column (Type = {2}, StructureId = 0x{3}) \"{0}\" has constant value not zero \"{1}\"",
                                    fieldInfo.Name, firstValue, fieldInfo.FieldType, structureId.ToString("X8"));
                            }
                            else // not array
                            {
                                if (firstValue.Equals(constValue)) continue;
                                if (fieldInfo.FieldType == typeof(Int32) &&
                                    ((Int32)firstValue == 0 && (firstValue.Equals(constValue) || constValue == null))) continue;
                                if (fieldInfo.FieldType == typeof(Int16) &&
                                    ((Int16)firstValue == 0 && (firstValue.Equals(constValue) || constValue == null))) continue;

                                message = String.Format("Warning: Private column (Type = {2}, StructureId = 0x{3}) \"{0}\" has constant value not zero \"{1}\"",
                                    fieldInfo.Name, firstValue, fieldInfo.FieldType, structureId.ToString("X8"));

                                if (outputAttribute != null && outputAttribute.ConstantValue != null) message += " (outputAttribute.ConstantValue is set)";
                            }
                        }
                    }
                    else // IsPublic
                    {
                        if (ignoreConstCheck) continue;

                        if (allEqual && fieldInfo.IsPublic && rowCount != 1 && (outputAttribute == null || outputAttribute.ConstantValue == null))
                        {
                            message = String.Format("Notice: Public column (Type = {2}, StructureId = 0x{3}) \"{0}\" has constant value \"{1}\"",
                                fieldInfo.Name, firstValue, fieldInfo.FieldType, structureId.ToString("X8"));
                        }
                    }

                    if (message == null) continue;

                    uint[] messageCounts;
                    if (outputMessages.TryGetValue(message, out messageCounts))
                    {
                        outputMessages[message] = new[] { messageCounts[0] + 1, structureId };
                    }
                    else
                    {
                        outputMessages.Add(message, new uint[] { 1, structureId });
                    }
                }

                //int bp3 = 0;
            }

            String previousStringId = null;
            StringWriter stringWriter = new StringWriter();
            foreach (KeyValuePair<String, uint[]> message in outputMessages)
            {
                String msg = message.Key;
                uint msgCount = message.Value[0];
                uint forStructureId = message.Value[1];
                uint structureCount = rowTypeCounts[forStructureId];

                if (structureCount != msgCount) continue; // if not equal, then we have a message in one table, but in another table it's not applicable

                String[] stringIds1 = (from dataTableAttribute in DataFile.DataFileMap
                                       where dataTableAttribute.Value.StructureId == forStructureId
                                       select dataTableAttribute.Key).ToArray();
                String[] stringIds2 = (from dataTableAttribute in DataFile.DataFileMapTestCenter
                                       where dataTableAttribute.Value.StructureId == forStructureId
                                       select dataTableAttribute.Key).ToArray();
                String[] stringIds3 = (from dataTableAttribute in DataFile.DataFileMapResurrection
                                       where dataTableAttribute.Value.StructureId == forStructureId
                                       select dataTableAttribute.Key).ToArray();
                String[] stringIds4 = (from dataTableAttribute in DataFile.DataFileMapMod
                                       where dataTableAttribute.Value.StructureId == forStructureId
                                       select dataTableAttribute.Key).ToArray();
                String stringIdPrepend = String.Join(",", stringIds1) + String.Join(",", stringIds2) + String.Join(",", stringIds3) + String.Join(",", stringIds4);

                if (previousStringId != stringIdPrepend)
                {
                    //Console.WriteLine(stringIdPrepend);
                    stringWriter.WriteLine(stringIdPrepend);
                    previousStringId = stringIdPrepend;
                }

                //Console.WriteLine(msg);
                stringWriter.WriteLine(msg);
            }
            File.WriteAllText(@"C:\asdf.txt", stringWriter.ToString());
        }
コード例 #2
0
ファイル: TestScripts.cs プロジェクト: khadoran/reanimator
        public static void CheckIdenticalFieldsToTCv4()
        {
            FileManager fileManager = new FileManager(Config.HglDir);
            fileManager.ExtractAllExcel();
            FileManager fileManagerTCv4 = new FileManager(Config.HglDir, FileManager.ClientVersions.TestCenter);

            fileManager.LoadTableFiles();
            fileManagerTCv4.LoadTableFiles(true);

            foreach (ExcelFile excelFile in fileManager.DataFiles.Values.Where(dataFile => dataFile.IsExcelFile))
            {
                Debug.WriteLine("Checking: " + excelFile.StringId);

                if (excelFile.StringId == "LANGUAGE" || excelFile.StringId == "REGION") continue; ;

                ObjectDelegator objectDelegator = fileManager.DataFileDelegators[excelFile.StringId];
                ObjectDelegator objectDelegatorTCv4 = fileManagerTCv4.DataFileDelegators["_TCv4_" + excelFile.StringId];

                foreach (ObjectDelegator.FieldDelegate fieldDelegate in objectDelegator)
                {
                    ObjectDelegator.FieldDelegate fieldDelegateTCv4 = objectDelegatorTCv4.GetFieldDelegate(fieldDelegate.Name);
                    if (fieldDelegateTCv4 == null)
                    {
                        if (fieldDelegate.Name == "blendOpAdventurer") continue; // field removed in TCv4 from WARDROBE_LAYER
                        if (fieldDelegate.Name == "unitVersionToGetSkillRespec") continue; // field removed in TCv4 from CHAR_DISPLAY
                        if (fieldDelegate.Name == "String") continue; // field removed in TCv4 from RECIPIES
                        if (fieldDelegate.Name == "unknown5") continue; // field removed in TCv4 from LEVEL
                        if (fieldDelegate.Name == "undefined11a") continue; // field removed in TCv4 from STATS

                        Debug.WriteLine(String.Format("Field '{0}' not found in TCv4 table.", fieldDelegate.Name));
                        continue;
                    }

                    // check excel attributes
                    ExcelFile.OutputAttribute outputAttribute = ExcelFile.GetExcelAttribute(fieldDelegate.Info);
                    ExcelFile.OutputAttribute outputAttributeTCv4 = ExcelFile.GetExcelAttribute(fieldDelegateTCv4.Info);
                    if (!Equals(outputAttribute, outputAttributeTCv4))
                    {
                        Debug.WriteLine(String.Format("Field '{0}' doesn't have matching excel attributes.", fieldDelegate.Name));
                    }

                    // check field types
                    if (fieldDelegate.FieldType.BaseType == typeof(Array))
                    {
                        if (fieldDelegateTCv4.FieldType.BaseType != typeof(Array))
                        {
                            Debug.WriteLine(String.Format("Field '{0}' is of type array, but TCv4 field is not.", fieldDelegate.Name));
                            continue;
                        }

                        MarshalAsAttribute arrayMarshal = (MarshalAsAttribute)fieldDelegate.Info.GetCustomAttributes(typeof(MarshalAsAttribute), false).First();
                        MarshalAsAttribute arrayMarshalTCv4 = (MarshalAsAttribute)fieldDelegateTCv4.Info.GetCustomAttributes(typeof(MarshalAsAttribute), false).First();

                        if (arrayMarshal.SizeConst == arrayMarshalTCv4.SizeConst) continue;

                        Debug.WriteLine(String.Format("Array fields '{0}' have lengths '{1}' != '{2}'", fieldDelegate.Name, arrayMarshal.SizeConst, arrayMarshalTCv4.SizeConst));
                    }

                    // check field accessor
                    if (fieldDelegate.IsPublic && !fieldDelegateTCv4.IsPublic)
                    {
                        Debug.WriteLine(String.Format("Field '{0}' is public, but not so in TCv4 class.", fieldDelegate.Name));
                    }
                    else if (fieldDelegate.IsPrivate && !fieldDelegateTCv4.IsPrivate)
                    {
                        Debug.WriteLine(String.Format("Field '{0}' is private, but not so in TCv4 class.", fieldDelegate.Name));
                    }

                    if (fieldDelegate.FieldType == fieldDelegateTCv4.FieldType || fieldDelegate.FieldType.BaseType == typeof(Enum)) continue;
                    Debug.WriteLine(String.Format("Field '{0}' of type '{1}' does not match TCv4 of type '{2}'", fieldDelegate.Name, fieldDelegate.FieldType, fieldDelegateTCv4.FieldType));
                }
            }
        }
コード例 #3
0
ファイル: TestScripts.cs プロジェクト: khadoran/reanimator
        /// <summary>
        /// This function is to test excel CSV cooking.
        /// </summary>
        public static void DoCookTest()
        {
            FileManager fileManager = new FileManager(Config.HglDir);
            fileManager.LoadTableFiles();
            fileManager.ExtractAllExcel();
            ExcelScript.GlobalDebug(true);

            foreach (PackFileEntry fileEntry in fileManager.FileEntries.Values)
            {
                if (!fileEntry.Name.EndsWith(ExcelFile.Extension)) continue;

                byte[] fileBytes = fileManager.GetFileBytes(fileEntry, true);
                Debug.Assert(fileBytes != null);
                String filePath = Path.Combine(Config.HglDir, fileEntry.Path);

                ExcelFile excelFile = new ExcelFile(fileBytes, fileEntry.Path);
                if (excelFile.Attributes.IsEmpty) continue;

                Console.WriteLine("Cooking file: " + fileEntry.Path);

                //if (!fileEntry.RelativeFullPathWithoutPatch.Contains("display_item")) continue;

                byte[] csvBytes = excelFile.ExportCSV(fileManager);
                File.WriteAllBytes(filePath.Replace(ExcelFile.Extension, ExcelFile.ExtensionDeserialised), csvBytes);
                ExcelFile excelFileCSV = new ExcelFile(fileEntry.Path);
                excelFileCSV.ParseCSV(csvBytes, fileManager);

                //byte[] recookedBytes = excelFileCSV.ToByteArray();
                byte[] csvBytes2 = excelFileCSV.ExportCSV(fileManager);

                //if (!csvBytes.SequenceEqual(csvBytes2))
                //{
                //    int b5p = 0;
                //}

                //if (excelFile.StringId == "GLOBAL_STRING")
                //{
                //    ExcelFile temp = new ExcelFile(recookedBytes, fileEntry.RelativeFullPathWithoutPatch);
                //    int bp1 = 0;
                //}

                //File.WriteAllBytes(filePath, recookedBytes);
            }

            //int bp = 0;
        }
コード例 #4
0
ファイル: TestScripts.cs プロジェクト: khadoran/reanimator
        /// <summary>
        /// Function to conver the TCv4 excel files to SP client formats.
        /// </summary>
        public static void ConvertTCv4ExcelToSP()
        {
            // init file manager and load excel files
            FileManager fileManager = new FileManager(Config.HglDir);
            fileManager.ExtractAllExcel();
            FileManager fileManagerTCv4 = new FileManager(Config.HglDir, FileManager.ClientVersions.TestCenter);

            fileManager.LoadTableFiles();
            fileManagerTCv4.LoadTableFiles(true);

            if (fileManager.DataFiles.Count == 0)
            {
                Debug.WriteLine("Error: No Excel files loaded!");
                return;
            }
            if (fileManagerTCv4.DataFiles.Count == 0)
            {
                Debug.WriteLine("Error: No TCv4 Excel files loaded!");
                return;
            }

            // convert tables
            //int converted = -1;
            Dictionary<String, ObjectDelegator> objectDelegators = new Dictionary<String, ObjectDelegator>();
            foreach (ExcelFile excelFile in fileManager.DataFiles.Values.Where(dataFile => dataFile.IsExcelFile))
            {
                //if (++converted >= 5) break;

                Debug.WriteLine("Converting Excel table " + excelFile.StringId + "...");

                // obviously don't want to convert this one
                if (excelFile.StringId == "EXCELTABLES") continue;

                // we can't convert stats as some index entries are hard-coded...
                if (excelFile.StringId == "STATS") continue;

                // game crashes with this converted...
                if (excelFile.StringId == "UNITMODES") continue;

                // don't bother with these two as there's no TCv4 equivalent (they don't matter anyways)
                if (excelFile.StringId == "LANGUAGE" || excelFile.StringId == "REGION") continue;

                // ensure we have a TCv4 version loaded
                String stringIdTCv4 = "_TCv4_" + excelFile.StringId;
                ExcelFile excelFileTCv4 = (ExcelFile)fileManagerTCv4.GetDataFile(stringIdTCv4);
                if (excelFileTCv4 == null)
                {
                    Debug.WriteLine("Error: TCv4 Excel file not found: " + stringIdTCv4);
                    continue;
                }

                // table specialisation stuffs
                bool isAchievements = false;
                bool isAffixes = false;
                bool isCharacterClass = false;
                //bool isCharDisplay = false;
                //bool isInventory = false;
                switch (excelFile.StringId)
                {
                    case "ACHIEVEMENTS":
                        isAchievements = true;
                        break;

                    case "AFFIXES":
                        isAffixes = true;
                        break;

                    case "CHARACTER_CLASS":
                        isCharacterClass = true;
                        break;

                    //case "CHARDISPLAY":
                    //    isCharDisplay = true;
                    //    break;

                    //case "INVENTORY":
                    //    isInventory = true;
                    //    break;
                }

                // genereal type-init stuffs; get our object delegators
                ObjectDelegator excelDelegator;
                ObjectDelegator excelDelegatorTCv41;
                ObjectDelegator excelDelegatorTCv42 = null;
                Type rowType = excelFile.Attributes.RowType;
                Type rowTypeTCv41 = excelFileTCv4.Attributes.RowType;
                Type rowTypeTCv42 = null;
                FieldInfo[] fieldInfos = rowType.GetFields();
                FieldInfo[] fieldInfosTCv41 = rowTypeTCv41.GetFields();
                FieldInfo[] fieldInfosTCv42 = null;

                // need to copy row headers (private field) as well
                FieldInfo rowHeaderField = rowType.GetField("header", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                FieldInfo rowHeaderFieldTCv4 = rowTypeTCv41.GetField("header", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                Array.Resize(ref fieldInfos, fieldInfos.Length + 1);
                Array.Resize(ref fieldInfosTCv41, fieldInfosTCv41.Length + 1);
                fieldInfos[fieldInfos.Length - 1] = rowHeaderField;
                fieldInfosTCv41[fieldInfosTCv41.Length - 1] = rowHeaderFieldTCv4;

                // create delegates
                if (!objectDelegators.TryGetValue(excelFile.StringId, out excelDelegator))
                {
                    excelDelegator = new ObjectDelegator(fieldInfos);
                    objectDelegators.Add(excelFile.StringId, excelDelegator);
                }
                if (!objectDelegators.TryGetValue(stringIdTCv4, out excelDelegatorTCv41))
                {
                    excelDelegatorTCv41 = new ObjectDelegator(fieldInfosTCv41);
                    objectDelegators.Add(stringIdTCv4, excelDelegatorTCv41);
                }

                // table specialisation inititialisation
                //// achievements
                Dictionary<int, int> unitTypeOverflow = null;
                if (isAchievements)
                {
                    unitTypeOverflow = new Dictionary<int, int>();
                }

                //// affixes
                ExcelFile affixGroupsTable = null;
                List<String> affixGroupsList = null;
                List<Int32> affixGroupWeightScripts = null;
                if (isAffixes)
                {
                    affixGroupsTable = fileManagerTCv4.GetDataFile("_TCv4_AFFIX_GROUPS") as ExcelFile;
                    affixGroupsList = new List<String>();
                    affixGroupWeightScripts = new List<Int32>();
                    Debug.Assert(affixGroupsTable != null);

                    rowTypeTCv42 = affixGroupsTable.Attributes.RowType;
                    fieldInfosTCv42 = rowTypeTCv42.GetFields();

                    FieldInfo rowHeaderFieldTCv42 = rowTypeTCv42.GetField("header", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                    Array.Resize(ref fieldInfosTCv42, fieldInfosTCv42.Length + 1);
                    fieldInfosTCv42[fieldInfosTCv42.Length - 1] = rowHeaderFieldTCv42;

                    excelDelegatorTCv42 = new ObjectDelegator(fieldInfosTCv42);
                }

                // debug: ensure we have same columns
                if (!isAchievements && !isCharacterClass && !isAffixes)
                {
                    bool hasSameFields = true;
                    foreach (FieldInfo fieldInfo in fieldInfos)
                    {
                        FieldInfo fieldInfoTCv4 = (from fi in fieldInfosTCv41
                                                   where fi.Name == fieldInfo.Name
                                                   select fi).FirstOrDefault();
                        if (fieldInfoTCv4 == null)
                        {
                            Debug.WriteLine("Field not found in TCv4 table: " + fieldInfo.Name);
                            hasSameFields = false;
                            continue;
                        }

                        if (fieldInfo.FieldType == fieldInfoTCv4.FieldType || fieldInfo.FieldType.BaseType == typeof(Enum)) continue;
                        Debug.WriteLine(String.Format("FieldInfo '{0}' of type '{1}' does not match TCv4 of type '{2}'", fieldInfo.Name, fieldInfo.FieldType, fieldInfoTCv4.FieldType));
                        hasSameFields = false;
                    }

                    if (!hasSameFields)
                    {
                        Debug.WriteLine("Error: The Excel types do not have the same fields!");
                        continue;
                    }
                }

                // begin conversion process
                Object[] rows = new Object[excelFileTCv4.Rows.Count];
                bool failed = false;
                int col = -1;
                byte[] scriptBuffer = new byte[1024];
                int scriptBufferOffset = 1; // first byte is null
                foreach (FieldInfo fieldInfo in fieldInfos) // loop by column
                {
                    col++;

                    ObjectDelegator.FieldGetValueDelegate getTCv4Value1 = null;
                    ObjectDelegator.FieldGetValueDelegate getTCv4Value2 = null;
                    ObjectDelegator.FieldGetValueDelegate getTCv4Value3 = null;
                    ObjectDelegator.FieldSetValueDelegate setValue1 = excelDelegator.GetFieldSetDelegate(fieldInfo.Name);
                    ObjectDelegator.FieldSetValueDelegate setValue2 = null;
                    ObjectDelegator.FieldGetValueDelegate getValue = excelDelegator.GetFieldGetDelegate(fieldInfo.Name);
                    ExcelFile.OutputAttribute outputAttribute = ExcelFile.GetExcelAttribute(fieldInfo);

                    // table specialisation stuffs
                    bool isUnitTypeField = false;                       // achievements
                    bool isItemField = false;                           // achievements
                    bool isUnitVersionToGetSkillRespec = false;         // character class
                    bool isGroup = false;                               // affixes
                    if (isAchievements && (fieldInfo.Name.StartsWith("unitType") || fieldInfo.Name == "item"))
                    {
                        if (fieldInfo.Name.StartsWith("unitType"))
                        {
                            String monsterFieldName = "monsterUnitType" + fieldInfo.Name.Last();
                            String itemFieldName = "itemUnitType" + fieldInfo.Name.Last();

                            getTCv4Value1 = excelDelegatorTCv41.GetFieldGetDelegate(monsterFieldName);
                            getTCv4Value2 = excelDelegatorTCv41.GetFieldGetDelegate(itemFieldName);
                            isUnitTypeField = true;
                        }
                        else if (fieldInfo.Name == "item")
                        {
                            isItemField = true;
                        }
                    }
                    else if (isCharacterClass && fieldInfo.Name == "unitVersionToGetSkillRespec")
                    {
                        isUnitVersionToGetSkillRespec = true;
                    }
                    else if (isAffixes && (fieldInfo.Name == "group" || fieldInfo.Name == "groupWeight"))
                    {
                        if (fieldInfo.Name == "groupWeight") continue; // we can skip it as we're setting it during group column

                        getTCv4Value1 = excelDelegatorTCv41.GetFieldGetDelegate(fieldInfo.Name);    // to get group affix index
                        getTCv4Value2 = excelDelegatorTCv42.GetFieldGetDelegate("name");            // to get group affix name
                        getTCv4Value3 = excelDelegatorTCv42.GetFieldGetDelegate("weight");          // to get group affix weight
                        setValue2 = excelDelegator.GetFieldSetDelegate("groupWeight");              // to set group weight
                        isGroup = true;
                    }
                    else
                    {
                        getTCv4Value1 = excelDelegatorTCv41.GetFieldGetDelegate(fieldInfo.Name);
                    }

                    // copy/convert field data
                    int row = -1;
                    foreach (Object rowTCv4 in excelFileTCv4.Rows) // loop by row
                    {
                        if (rows[++row] == null) rows[row] = Activator.CreateInstance(excelFile.Attributes.RowType);

                        Object value;

                        // achievements special stuffs
                        if (isAchievements && (isUnitTypeField || isItemField))
                        {
                            if (isUnitTypeField)
                            {
                                int monsterValue = (int)getTCv4Value1(rowTCv4);
                                int itemValue = (int)getTCv4Value2(rowTCv4);

                                if (monsterValue != 0 && itemValue != 0)
                                {
                                    Debug.Assert(!unitTypeOverflow.ContainsKey(row));

                                    unitTypeOverflow.Add(row, itemValue);
                                    itemValue = 0;
                                }
                                else if (monsterValue == 0 && itemValue == 0 && unitTypeOverflow.ContainsKey(row))
                                {
                                    itemValue = unitTypeOverflow[row];
                                    unitTypeOverflow.Remove(row);
                                }

                                value = (itemValue == 0) ? monsterValue : itemValue;
                            }
                            else
                            {
                                value = 0;
                            }
                        }
                        else if (isCharacterClass && isUnitVersionToGetSkillRespec)
                        {
                            value = getValue(excelFile.Rows[row]);
                        }
                        else if (isAffixes && isGroup)
                        {
                            Debug.Assert(getTCv4Value1 != null && getTCv4Value2 != null && getTCv4Value3 != null);

                            int affixGroupRowIndex = (int)getTCv4Value1(rowTCv4);

                            if (affixGroupRowIndex == -1)
                            {
                                setValue2(rows[row], 0);
                                value = -1;
                            }
                            else
                            {
                                int affixGroupStringOffset = (int)getTCv4Value2(affixGroupsTable.Rows[affixGroupRowIndex]);
                                int affixGroupWeight = (int)getTCv4Value3(affixGroupsTable.Rows[affixGroupRowIndex]);

                                setValue2(rows[row], scriptBufferOffset);
                                FileTools.WriteToBuffer(ref scriptBuffer, ref scriptBufferOffset, new[] { (Int32)ExcelScript.ScriptOpCodes.Push, affixGroupWeight, 0 }.ToByteArray());

                                String affixGroupString = affixGroupsTable.ReadStringTable(affixGroupStringOffset);
                                int affixGroupStringIndex = affixGroupsList.IndexOf(affixGroupString);
                                if (affixGroupStringIndex == -1)
                                {
                                    affixGroupStringIndex = affixGroupsList.Count;
                                    affixGroupsList.Add(affixGroupString);
                                }

                                value = affixGroupStringIndex;
                            }
                        }
                        else
                        {
                            Debug.Assert(getTCv4Value1 != null);

                            value = getTCv4Value1(rowTCv4);
                        }

                        if (outputAttribute == null)
                        {
                            setValue1(rows[row], value);
                            continue;
                        }

                        if (outputAttribute.IsBitmask)
                        {
                            if (value.GetType().BaseType != typeof(Enum))
                            {
                                Debug.WriteLine("Error: IsBitmask is not of type Enum: " + fieldInfo.Name);
                                failed = true;
                                break;
                            }

                            Type spBitMask = fieldInfo.FieldType;
                            Type tcBitMask = value.GetType();
                            uint currentMask = (uint)value;
                            uint convertedMask = 0;

                            for (int i = 0; i < 32; i++)
                            {
                                uint testBit = (uint)1 << i;
                                if ((currentMask & testBit) == 0) continue;

                                String bitString = Enum.GetName(tcBitMask, testBit);
                                if (bitString == null) continue;

                                if (Enum.IsDefined(spBitMask, bitString))
                                {
                                    convertedMask += (uint)Enum.Parse(spBitMask, bitString);
                                }
                            }

                            value = convertedMask;
                        }
                        else if (outputAttribute.IsScript)
                        {
                            //int scriptOffset = (int)value;
                            //if (scriptOffset != 0)
                            //{
                            //    ExcelScript excelScriptTCv4 = new ExcelScript(fileManagerTCv4);

                            //    try
                            //    {
                            //        excelScriptTCv4.Decompile(excelFileTCv4.ScriptBuffer, scriptOffset, null, excelFileTCv4.StringId, row, col, fieldInfo.Name);
                            //    }
                            //    catch (Exception e)
                            //    {
                            //        Debug.WriteLine("TCv4 Decompile Error:\n" + e);
                            //        continue;
                            //    }

                            //    ExcelScript excelScriptCompiler = new ExcelScript(fileManagerTCv4, true, true);

                            //    try
                            //    {
                            //        excelScriptCompiler.Compile(excelScriptTCv4.ScriptString, null, excelFileTCv4.StringId, row, col, fieldInfo.Name);
                            //        value = scriptBufferOffset;
                            //    }
                            //    catch (Exceptions.ScriptUnknownFunctionException e)
                            //    {
                            //        if (isCharDisplay || isInventory)
                            //        {
                            //            value = 0;
                            //        }
                            //        else
                            //        {
                            //            Debug.WriteLine("SP Recompile Error: \n" + excelScriptTCv4.ScriptString + "\n" + e);
                            //            value = 0;
                            //            //continue;
                            //        }
                            //    }
                            //    catch (Exception e)
                            //    {
                            //        Debug.WriteLine("SP Recompile Error: \n" + excelScriptTCv4.ScriptString + "\n" + e);
                            //        value = 0;
                            //        //continue;
                            //    }

                            //    if ((int)value != 0)
                            //    {
                            //        FileTools.WriteToBuffer(ref scriptBuffer, ref scriptBufferOffset, excelScriptCompiler.ScriptCode.ToByteArray());
                            //    }
                            //}
                        }

                        setValue1(rows[row], value);
                    }

                    if (failed) break;
                }
                if (failed)
                {
                    Debug.WriteLine("Error: Excel conversion failed: " + excelFile.StringId);
                    continue;
                }

                // finish conversion process by "changing" the TCv4 type
                excelFileTCv4.ConvertType(excelFile, rows);
                if (scriptBufferOffset != 1)
                {
                    excelFileTCv4.SetScriptCode(scriptBuffer);
                }

                if (isAffixes)
                {
                    excelFileTCv4.SetSecondaryStringsCollection(affixGroupsList);
                }

                byte[] convertedBytes = excelFileTCv4.ToByteArray();
                String writePath = Path.Combine(Config.HglDir, excelFile.FilePath);
                String backupPath = writePath + ".bak";

                if (File.Exists(backupPath)) File.Delete(backupPath);
                File.Move(writePath, backupPath);
                File.WriteAllBytes(writePath, convertedBytes);

                //int bp2 = 0;
            }

            //int bp1 = 0;
        }