/// <summary> /// /// </summary> /// <param name="script"></param> /// <param name="fileManager"></param> /// <returns></returns> public static bool ApplyScript(Script script, ref FileManager fileManager) { #region Table Modifications if (script.Tables != null) { foreach (Script.Table table in script.Tables) { string tableID = table.ID.ToUpper(); if (fileManager.DataFiles.ContainsKey(tableID) == false) { Console.WriteLine(String.Format("Error: The table id is incorrect or does not exist: {0} ", tableID)); continue; } ExcelFile dataTable = fileManager.DataFiles[tableID] as ExcelFile; if (dataTable == null) { Console.WriteLine(String.Format("Error: Could not open {0} due to null reference.", tableID)); continue; } foreach (Script.Table.Entity entity in table.Entities) { foreach (Script.Table.Entity.Attribute attribute in entity.Attributes) { string whereColumn = String.Empty; string[] whereValue = null; int step = 0; int min = 1; int max = 0; int last = 0; //for recursive function string function; int[] list; try { //determine the range if (entity.ID.Contains(",")) { string[] explode = entity.ID.Split(','); list = new int[explode.Length]; for (int i = 0; i < list.Length; i++) { list[i] = Convert.ToInt32(explode[i]); } } else { if (entity.ID.Contains("*")) { min = 0; max = dataTable.Count - 1; } else if (entity.ID.Contains("-")) { int idx = entity.ID.IndexOf('-'); int len = entity.ID.Length - idx - 1; min = Convert.ToInt32(entity.ID.Substring(0, idx)); max = Convert.ToInt32(entity.ID.Substring(idx + 1, len)); } else { min = Convert.ToInt32(entity.ID); max = Convert.ToInt32(entity.ID); } int listlen = max - min + 1; list = new int[listlen]; int i = 0; for (int row = min; row <= max; row++) { list[i++] = row; } } //check for where condition if (attribute.Where != null) { int equalsIndex = attribute.Where.IndexOf('='); if (equalsIndex == -1) { Console.WriteLine("Bad syntax in where condition."); return(false); } whereColumn = attribute.Where.Substring(0, equalsIndex); string whereValueString = attribute.Where.Substring(equalsIndex + 1, attribute.Where.Length - equalsIndex - 1); if (whereValueString.Contains('|')) { whereValue = whereValueString.Split('|'); } else { whereValue = new string[] { whereValueString }; } } //determine function if (attribute.Bit != null) { function = "bitwise"; } else if (attribute.Operation == null) { function = "replace"; } else if (attribute.Operation.Contains("*")) { function = "multiply"; } else if (attribute.Operation.Contains("/")) { function = "divide"; } else if (attribute.Operation.Contains("+")) { string s = attribute.Operation.Remove(0); step = Convert.ToInt32(s); function = "recursive"; } else if (attribute.Operation.Contains("-")) { step = Convert.ToInt32(attribute.Operation); function = "recursive"; } else { continue; // syntax error } //main loop, alters the dataset foreach (int row in list) { object obj = null; string col = attribute.ID; Type type = dataTable.DataType.GetField(col).FieldType; Object currentValue = dataTable.DataType.GetField(col).GetValue(dataTable.Rows[row]); if (String.IsNullOrEmpty(whereColumn) == false) { Type typeWhere = dataTable.DataType.GetField(whereColumn).FieldType; Object currentValueWhere = dataTable.DataType.GetField(whereColumn).GetValue(dataTable.Rows[row]); if (whereValue.Where(val => FileTools.StringToObject(val, typeWhere).Equals(currentValueWhere)).Any() == false) { continue; } } switch (function) { case "replace": obj = FileTools.StringToObject(attribute.Data, type); break; case "multiply": if (type.Equals(typeof(int))) { obj = (int)currentValue * Convert.ToInt32(attribute.Data); } else if (type.Equals(typeof(float))) { obj = (float)currentValue * Convert.ToSingle(attribute.Data); } break; case "divide": if (type.Equals(typeof(int))) { obj = (int)currentValue / Convert.ToInt32(attribute.Data); } else if (type.Equals(typeof(float))) { obj = (float)currentValue / Convert.ToSingle(attribute.Data); } break; case "bitwise": uint bit = (uint)Enum.Parse(type, attribute.Bit, true); uint mask = (uint)currentValue; bool flick = Convert.ToBoolean(attribute.Data); bool current = (mask & bit) > 0; if (flick != current) { obj = mask ^= bit; } else { obj = mask; } break; case "recursive": if (row.Equals(min)) //first time only { if (type.Equals(typeof(int))) { obj = Convert.ToInt32(attribute.Data); last = (int)obj; } } else { last += step; obj = last; } break; } dataTable.DataType.GetField(col).SetValue(dataTable.Rows[row], obj); } } catch (Exception ex) { ExceptionLogger.LogException(ex); return(false); } } } fileManager.DataFiles[tableID] = dataTable; } } #endregion #region Extraction Script if (script.Extraction != null) { string sourcePath = Path.Combine(fileManager.HellgateDataPath, script.Extraction.Source + ".idx"); string destinationPath = sourcePath.Replace(script.Extraction.Source, script.Extraction.Destination); // Check source index exists if (File.Exists(sourcePath) == false) { return(false); } // Try open the index file //byte[] sbuffer; PackFile sourceIndex = new IndexFile(sourcePath); PackFile destinationIndex = new IndexFile(destinationPath); try { sourceIndex.ParseFileBytes(File.ReadAllBytes(sourcePath)); } catch (Exception ex) { Console.WriteLine("Error: {0} filed to load. Make sure you have run Hellgate London at least once (MP version for MP files) before installating this modification.", sourceIndex); ExceptionLogger.LogException(ex); return(false); } sourceIndex.BeginDatReading(); // Extract each path/file foreach (PackFileEntry fileEntry in sourceIndex.Files) { if (!script.Extraction.paths.Where(p => Regex.IsMatch(fileEntry.Path, p.Replace(@"\", @"\\"))).Any()) { continue; } byte[] fileBytes = sourceIndex.GetFileBytes(fileEntry); //if (fileEntry.FileNameString.Contains(XmlCookedFile.FileExtention)) //{ // try // { // XmlCookedFile xmlCookedFile = new XmlCookedFile(); // xmlCookedFile.Uncook(fileBytes); // XmlCookedFile reCooked = new XmlCookedFile(); // fileBytes = reCooked.CookXmlDocument(xmlCookedFile.XmlDoc); // } // catch (Exception) { } //} destinationIndex.AddFile(fileEntry.Directory, fileEntry.Name, fileBytes); } // Write the file byte[] ibuffer = destinationIndex.ToByteArray(); Crypt.Encrypt(ibuffer); try { File.WriteAllBytes(destinationIndex.Path, ibuffer); } catch (Exception ex) { ExceptionLogger.LogException(ex); return(false); } finally { sourceIndex.EndDatAccess(); sourceIndex.Dispose(); destinationIndex.Dispose(); } } #endregion return(true); }