public static string PropertyToText(Property p, PCCObject pcc) { string s = ""; s = "Name: " + pcc.Names[p.Name]; s += " | Type: " + TypeToString((int)p.TypeVal); s += " | Size: " + p.Value.len.ToString(); switch (p.TypeVal) { case Type.StructProperty: s += " \"" + pcc.getNameEntry(p.Value.IntValue) + "\" with " + p.Value.Array.Count.ToString() + " bytes"; break; case Type.IntProperty: case Type.ObjectProperty: case Type.BoolProperty: case Type.StringRefProperty: s += " Value: " + p.Value.IntValue.ToString(); break; case Type.FloatProperty: byte[] buff = BitConverter.GetBytes(p.Value.IntValue); float f = BitConverter.ToSingle(buff, 0); s += " | Value: " + f.ToString(); break; case Type.NameProperty: s += " " + pcc.Names[p.Value.IntValue]; break; case Type.ByteProperty: s += " | Value: \"" + p.Value.StringValue + "\" with \"" + pcc.getNameEntry(p.Value.IntValue) + "\""; break; case Type.ArrayProperty: s += " bytes"; //Value: " + p.Value.Array.Count.ToString() + " Elements"; break; case Type.StrProperty: if (p.Value.StringValue.Length == 0) { break; } s += " Value: " + p.Value.StringValue.Substring(0, p.Value.StringValue.Length - 1); break; } return(s); }
private static Type getType(PCCObject pcc, int type) { switch (pcc.getNameEntry(type)) { case "None": return(Type.None); case "StructProperty": return(Type.StructProperty); case "IntProperty": return(Type.IntProperty); case "FloatProperty": return(Type.FloatProperty); case "ObjectProperty": return(Type.ObjectProperty); case "NameProperty": return(Type.NameProperty); case "BoolProperty": return(Type.BoolProperty); case "ByteProperty": return(Type.ByteProperty); case "ArrayProperty": return(Type.ArrayProperty); case "DelegateProperty": return(Type.DelegateProperty); case "StrProperty": return(Type.StrProperty); case "StringRefProperty": return(Type.StringRefProperty); default: return(Type.Unknown); } }
public static Property getPropOrNull(PCCObject pcc, byte[] data, int start, string propName) { List <Property> props = ReadProp(pcc, data, 0); foreach (Property prop in props) { if (pcc.getNameEntry(prop.Name) == propName) { return(prop); } } return(null); }
public static Property getPropOrNull(PCCObject pcc, PCCObject.ExportEntry export, string propName) { List <Property> props = getPropList(pcc, export); foreach (Property prop in props) { if (pcc.getNameEntry(prop.Name) == propName) { return(prop); } } return(null); }
private static PropertyValue ReadValue(PCCObject pcc, byte[] raw, int start, int type) { PropertyValue v = new PropertyValue(); switch (pcc.Names[type]) { case "IntProperty": case "FloatProperty": case "ObjectProperty": case "StringRefProperty": v.IntValue = BitConverter.ToInt32(raw, start); v.len = 4; break; case "NameProperty": v.IntValue = BitConverter.ToInt32(raw, start); var nameRef = new NameReference(); nameRef.index = v.IntValue; nameRef.count = BitConverter.ToInt32(raw, start + 4); nameRef.Name = pcc.getNameEntry(nameRef.index); if (nameRef.count > 0) { nameRef.Name += "_" + (nameRef.count - 1); } v.NameValue = nameRef; v.len = 8; break; case "BoolProperty": if (start < raw.Length) { v.IntValue = raw[start]; } v.len = 1; break; } return(v); }
public static CustomProperty PropertyToGrid(Property p, PCCObject pcc) { string cat = p.TypeVal.ToString(); CustomProperty pg; NameProp pp; switch (p.TypeVal) { case Type.BoolProperty: pg = new CustomProperty(pcc.Names[p.Name], cat, (p.Value.IntValue == 1), typeof(bool), false, true); break; case Type.FloatProperty: byte[] buff = BitConverter.GetBytes(p.Value.IntValue); float f = BitConverter.ToSingle(buff, 0); pg = new CustomProperty(pcc.Names[p.Name], cat, f, typeof(float), false, true); break; case Type.ByteProperty: if (p.Size != 8) { pg = new CustomProperty(pcc.Names[p.Name], cat, (byte)p.Value.IntValue, typeof(byte), false, true); } else { pp = new NameProp(); pp.name = pcc.getNameEntry(p.Value.IntValue); pp.nameindex = p.Value.IntValue; pg = new CustomProperty(pcc.Names[p.Name], cat, pp, typeof(NameProp), false, true); } break; case Type.NameProperty: pp = new NameProp(); pp.name = pcc.getNameEntry(p.Value.IntValue); pp.nameindex = p.Value.IntValue; pg = new CustomProperty(pcc.Names[p.Name], cat, pp, typeof(NameProp), false, true); break; case Type.ObjectProperty: ObjectProp ppo = new ObjectProp(); ppo.objectName = pcc.getObjectName(p.Value.IntValue); ppo.index = p.Value.IntValue; pg = new CustomProperty(pcc.Names[p.Name], cat, ppo, typeof(ObjectProp), false, true); break; case Type.StrProperty: pg = new CustomProperty(pcc.Names[p.Name], cat, p.Value.StringValue, typeof(string), false, true); break; case Type.ArrayProperty: pg = new CustomProperty(pcc.Names[p.Name], cat, BitConverter.ToInt32(p.raw, 24) + " elements", typeof(string), false, true); break; case Type.StructProperty: string structType = pcc.getNameEntry(p.Value.IntValue); if (structType == "Color") { ColorProp cp = new ColorProp(); cp.name = structType; cp.nameindex = p.Value.IntValue; System.Drawing.Color color = System.Drawing.Color.FromArgb(BitConverter.ToInt32(p.raw, 32)); cp.Alpha = color.A; cp.Red = color.R; cp.Green = color.G; cp.Blue = color.B; pg = new CustomProperty(pcc.Names[p.Name], cat, cp, typeof(ColorProp), false, true); } else if (structType == "Vector") { VectorProp vp = new VectorProp(); vp.name = structType; vp.nameindex = p.Value.IntValue; vp.X = BitConverter.ToSingle(p.raw, 32); vp.Y = BitConverter.ToSingle(p.raw, 36); vp.Z = BitConverter.ToSingle(p.raw, 40); pg = new CustomProperty(pcc.Names[p.Name], cat, vp, typeof(VectorProp), false, true); } else if (structType == "Rotator") { RotatorProp rp = new RotatorProp(); rp.name = structType; rp.nameindex = p.Value.IntValue; rp.Pitch = (float)BitConverter.ToInt32(p.raw, 32) * 360f / 65536f; rp.Yaw = (float)BitConverter.ToInt32(p.raw, 36) * 360f / 65536f; rp.Roll = (float)BitConverter.ToInt32(p.raw, 40) * 360f / 65536f; pg = new CustomProperty(pcc.Names[p.Name], cat, rp, typeof(RotatorProp), false, true); } else if (structType == "LinearColor") { LinearColorProp lcp = new LinearColorProp(); lcp.name = structType; lcp.nameindex = p.Value.IntValue; lcp.Red = BitConverter.ToSingle(p.raw, 32); lcp.Green = BitConverter.ToSingle(p.raw, 36); lcp.Blue = BitConverter.ToSingle(p.raw, 40); lcp.Alpha = BitConverter.ToSingle(p.raw, 44); pg = new CustomProperty(pcc.Names[p.Name], cat, lcp, typeof(VectorProp), false, true); } else { StructProp ppp = new StructProp(); ppp.name = structType; ppp.nameindex = p.Value.IntValue; byte[] buf = new byte[p.Value.Array.Count()]; for (int i = 0; i < p.Value.Array.Count(); i++) { buf[i] = (byte)p.Value.Array[i].IntValue; } List <int> buf2 = new List <int>(); for (int i = 0; i < p.Value.Array.Count() / 4; i++) { buf2.Add(BitConverter.ToInt32(buf, i * 4)); } ppp.data = buf2.ToArray(); pg = new CustomProperty(pcc.Names[p.Name], cat, ppp, typeof(StructProp), false, true); } break; default: pg = new CustomProperty(pcc.Names[p.Name], cat, p.Value.IntValue, typeof(int), false, true); break; } return(pg); }
public static byte[] getDefaultClassValue(PCCObject pcc, string className, bool fullProps = false) { if (Structs.ContainsKey(className)) { bool isImmutable = ImmutableStructs.Contains(className); ClassInfo info = Structs[className]; PCCObject importPCC; try { importPCC = new PCCObject(Path.Combine(TransplanterLib.GamePath, @"BIOGame\" + info.pccPath)); } catch (Exception) { return null; } byte[] buff; //Plane and CoverReference inherit from other structs, meaning they don't have default values (who knows why) //thus, I have hardcoded what those default values should be if (className == "Plane") { buff = PlaneDefault; } else if (className == "CoverReference") { buff = CoverReferenceDefault; } else { buff = importPCC.Exports[info.exportIndex].Data.Skip(0x24).ToArray(); } List<PropertyReader.Property> Props = PropertyReader.ReadProp(importPCC, buff, 0); MemoryStream m = new MemoryStream(); foreach (PropertyReader.Property p in Props) { string propName = importPCC.getNameEntry(p.Name); //check if property is transient, if so, skip (neither of the structs that inherit have transient props) if (info.properties.ContainsKey(propName) || propName == "None" || info.baseClass != "Class") { if (isImmutable && !fullProps) { PropertyReader.ImportImmutableProperty(pcc, importPCC, p, className, m, true); } else { PropertyReader.ImportProperty(pcc, importPCC, p, className, m, true); } } } return m.ToArray(); } else if (Classes.ContainsKey(className)) { ClassInfo info = Structs[className]; PCCObject importPCC; try { importPCC = new PCCObject(Path.Combine(TransplanterLib.GamePath, @"BIOGame\" + info.pccPath)); } catch (Exception) { return null; } PCCObject.ExportEntry entry = pcc.Exports[info.exportIndex + 1]; List<PropertyReader.Property> Props = PropertyReader.getPropList(importPCC, entry); MemoryStream m = new MemoryStream(entry.DataSize - 4); foreach (PropertyReader.Property p in Props) { if (!info.properties.ContainsKey(importPCC.getNameEntry(p.Name))) { //property is transient continue; } PropertyReader.ImportProperty(pcc, importPCC, p, className, m); } return m.ToArray(); } return null; }
public static Property getPropOrNull(PCCObject pcc, byte[] data, int start, string propName) { List<Property> props = ReadProp(pcc, data, 0); foreach (Property prop in props) { if (pcc.getNameEntry(prop.Name) == propName) { return prop; } } return null; }
public static void dumpModMakerWeaponDynamicSQL(string filepath) { string[] files = Directory.GetFiles(filepath,"*.pcc"); foreach (String path in files) { string fname = Path.GetFileName(path); if (!fname.StartsWith("SFXWeapon_")) continue; string module = "UNDEFINED"; string pathstr = "UNDEFINED"; if (path.ToUpper().Contains("\\DLC\\DLC_CON_")) { string dlcid = path.Substring(path.IndexOf("\\DLC\\DLC_CON_") + 13); int endindex = dlcid.IndexOf("\\"); dlcid = dlcid.Substring(0, endindex).ToUpper(); switch (dlcid) { case "MP1": module = "RESURGENCE"; pathstr = "/BIOGame/DLC/DLC_CON_MP1/CookedPCConsole/" + Path.GetFileName(path); break; case "MP2": module = "REBELLION"; pathstr = "/BIOGame/DLC/DLC_CON_MP2/CookedPCConsole/" + Path.GetFileName(path); break; case "MP3": module = "EARTH"; pathstr = "/BIOGame/DLC/DLC_CON_MP3/CookedPCConsole/" + Path.GetFileName(path); break; case "MP4": module = "RETALIATION"; pathstr = "/BIOGame/DLC/DLC_CON_MP4/CookedPCConsole/" + Path.GetFileName(path); break; case "MP5": module = "RECKONING"; pathstr = "/BIOGame/DLC/DLC_CON_MP5/CookedPCConsole/" + Path.GetFileName(path); break; } } PCCObject pcc = new PCCObject(path); try { string savepath = Path.GetFileNameWithoutExtension(path) + ".sql"; using (StreamWriter stringoutput = new StreamWriter(Directory.GetParent(path) + "\\"+ savepath)) { Console.WriteLine("outputting to " + Directory.GetParent(path) + savepath); int numDone = 1; int numTotal = pcc.Exports.Count; int lastProgress = 0; writeVerboseLine("Enumerating exports"); Boolean needsFlush = false; int index = 0; foreach (PCCObject.ExportEntry exp in pcc.Exports) { index++; //filter switch (exp.ObjectName) { case "AnimNodeSequence": case "BioAnimNodeSequenceMirror": continue; } if (exp.PackageFullName.StartsWith("EffectsMaterials")) { continue; } if (exp.PackageFullName.ToUpper().StartsWith("BIOG")) { continue; } if (exp.PackageFullName.ToUpper().StartsWith("BIOVFX")) { continue; } if (exp.PackageFullName.ToUpper().StartsWith("WWISE")) { continue; } if (exp.PackageFullName.ToUpper().StartsWith("GUI_SF")) { continue; } if (!exp.ObjectName.Contains("Default__SFXWeapon")) { continue; } if (!exp.ObjectName.Contains(Path.GetFileNameWithoutExtension(path))) { continue; } List<PropertyReader.Property> p; Console.WriteLine("Reading props from export: " + exp.PackageFullName + "." + exp.ObjectName); string catname = exp.ObjectName.Substring(19); p = PropertyReader.getPropList(pcc, exp); string[] lockoutpropnames = { "Damage", "StatBarDamage" }; if (p.Count > 0) { Boolean isfirst = true; foreach (Property pr in p) { if (pr.TypeVal == PropertyReader.Type.StructProperty) { //int idx = BitConverter.ToInt32(exp.Data, pr.offsetval + 24); string structtype = pcc.getNameEntry(pr.Value.IntValue); //Console.Write(pcc.getNameEntry(pr.Name) + " - " + structtype); switch (structtype) { case "ScaledFloat": //Console.WriteLine("prop offset: " + (pr.offsetval + 0x38).ToString("X8")); double x = BitConverter.ToSingle(exp.Data, pr.offsetval + 4 + 0x1C); double y = BitConverter.ToSingle(exp.Data, pr.offsetval + 4 + 0x1C * 2); //Console.WriteLine(" " + x.ToString("0.0######") + " to " + y.ToString("0.0######")); stringoutput.WriteLine("INSERT INTO dynamicmixinlibrary VALUES(null,'" + catname + " - " + pcc.getNameEntry(pr.Name) + " Level 1'," + "'Defines " + pcc.getNameEntry(pr.Name) + " per pellet for " + catname + ".', 'HINT', '" + module + "', '" + pathstr + "', " + new FileInfo(pcc.pccFileName).Length.ToString() + "," + "0x" + (pr.offsetval + 4 + 0x1C + exp.DataOffset).ToString("X8") + ",3,null,null,null," + x.ToString("0.0####") + ",null,null,null,null,null,null,0,null,1001, 0);"); stringoutput.WriteLine("INSERT INTO dynamicmixinlibrary VALUES(null,'" + catname + " - " + pcc.getNameEntry(pr.Name) + " Level 10'," + "'Defines " + pcc.getNameEntry(pr.Name) + " per pellet for " + catname + ".', 'HINT', '" + module + "', '" + pathstr + "', " + new FileInfo(pcc.pccFileName).Length.ToString() + "," + "0x" + (pr.offsetval + 4 + 0x1C * 2 + exp.DataOffset).ToString("X8") + ",3,null,null,null," + y.ToString("0.0####") + ",null,null,null,null,null,null,0,null,1001, 0);"); break; } } continue; if (pr.TypeVal == PropertyReader.Type.FloatProperty) { if (isfirst) { stringoutput.WriteLine(" -- EXPORT #" + index + " " + exp.PackageFullName + "." + exp.ObjectName); isfirst = false; } Console.WriteLine("FLOAT PROPERTY: " + pcc.getNameEntry(pr.Name) + " at 0x" + (pr.offsetval + exp.DataOffset).ToString("X8")); byte[] ibuff = BitConverter.GetBytes(pr.Value.IntValue); float f = BitConverter.ToSingle(ibuff, 0); stringoutput.WriteLine("INSERT INTO dynamicmixinlibrary VALUES(null,'CATNAME - " + pcc.getNameEntry(pr.Name) + "'," + "'PLACEHOLDERDESC', 'HINT', 'TARGETMODULE', 'TARGETPATH', " + new FileInfo(pcc.pccFileName).Length.ToString() + "," + "0x" + (pr.offsetval + exp.DataOffset).ToString("X8") + ",3,null,null,null," + f.ToString() + ",null,null,null,null,null,null,0.001,null,CATEGORY, 0);"); } if (pr.TypeVal == PropertyReader.Type.IntProperty) { if (isfirst) { stringoutput.WriteLine(" -- EXPORT #" + index + " " + exp.PackageFullName + "." + exp.ObjectName); isfirst = false; } Console.WriteLine("INT PROPERTY: " + pcc.getNameEntry(pr.Name) + " at 0x" + (pr.offsetval + exp.DataOffset).ToString("X8")); stringoutput.WriteLine("INSERT INTO dynamicmixinlibrary VALUES(null,'CATNAME - " + pcc.getNameEntry(pr.Name) + "'," + "'PLACEHOLDERDESC', 'HINT', 'TARGETMODULE', 'TARGETPATH', " + new FileInfo(pcc.pccFileName).Length.ToString() + "," + "0x" + (pr.offsetval + exp.DataOffset).ToString("X8") + ",0," + pr.Value.IntValue.ToString() + ",null,null,null,0,null,null,null,null,null,0,null,CATEGORY, 0);"); } } Console.WriteLine(); } // } // if (data) // { // stringoutput.WriteLine("==============Data=============="); // stringoutput.WriteLine(BitConverter.ToString(exp.Data)); // } //} //numDone++; } //stringoutput.WriteLine("--End of " + datasets); if (needsFlush) { Console.WriteLine(); } stringoutput.Close(); } } catch (Exception e) { Console.WriteLine("Exception parsing " + path + "\n" + e.Message); } } }
public static void ImportImmutableProperty(PCCObject pcc, PCCObject importpcc, Property p, string className, System.IO.MemoryStream m, bool inStruct = false) { string name = importpcc.getNameEntry(p.Name); int idxname = pcc.FindNameOrAdd(name); if (name == "None") return; string type = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 8)); int idxtype = pcc.FindNameOrAdd(type); string name2; int idxname2; int size, count, pos; List<Property> Props; switch (type) { case "IntProperty": case "FloatProperty": case "ObjectProperty": case "StringRefProperty": m.Write(BitConverter.GetBytes(p.Value.IntValue), 0, 4); break; case "NameProperty": m.Write(BitConverter.GetBytes(pcc.FindNameOrAdd(importpcc.getNameEntry(p.Value.IntValue))), 0, 4); //preserve index or whatever the second part of a namereference is m.Write(p.raw, 28, 4); break; case "BoolProperty": m.WriteByte((byte)p.Value.IntValue); break; case "BioMask4Property": m.WriteByte((byte)p.Value.IntValue); break; case "ByteProperty": name2 = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 24)); idxname2 = pcc.FindNameOrAdd(name2); if (p.Size == 8) { m.Write(BitConverter.GetBytes(pcc.FindNameOrAdd(importpcc.getNameEntry(p.Value.IntValue))), 0, 4); m.Write(new byte[4], 0, 4); } else { m.WriteByte(p.raw[32]); } break; case "StrProperty": name2 = p.Value.StringValue; m.Write(BitConverter.GetBytes(-name2.Length), 0, 4); foreach (char c in name2) { m.WriteByte((byte)c); m.WriteByte(0); } break; case "StructProperty": size = BitConverter.ToInt32(p.raw, 16); name2 = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 24)); idxname2 = pcc.FindNameOrAdd(name2); pos = 32; Props = new List<Property>(); try { Props = ReadProp(importpcc, p.raw, pos); } catch (Exception) { } if (Props.Count == 0 || Props[0].TypeVal == Type.Unknown) { for (int i = 0; i < size; i++) m.WriteByte(p.raw[32 + i]); } else { foreach (Property pp in Props) ImportImmutableProperty(pcc, importpcc, pp, className, m, inStruct); } break; case "ArrayProperty": size = BitConverter.ToInt32(p.raw, 16); count = BitConverter.ToInt32(p.raw, 24); UnrealObjectInfo.ArrayType arrayType = UnrealObjectInfo.getArrayType(className, importpcc.getNameEntry(p.Name), inStruct); pos = 28; List<Property> AllProps = new List<Property>(); if (arrayType == UnrealObjectInfo.ArrayType.Struct) { for (int i = 0; i < count; i++) { Props = new List<Property>(); try { Props = ReadProp(importpcc, p.raw, pos); } catch (Exception) { } AllProps.AddRange(Props); if (Props.Count != 0) { pos = Props[Props.Count - 1].offend; } } } m.Write(BitConverter.GetBytes(count), 0, 4); if (AllProps.Count != 0) { foreach (Property pp in AllProps) ImportImmutableProperty(pcc, importpcc, pp, className, m, inStruct); } else if (arrayType == UnrealObjectInfo.ArrayType.Name) { for (int i = 0; i < count; i++) { string s = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 28 + i * 8)); m.Write(BitConverter.GetBytes(pcc.FindNameOrAdd(s)), 0, 4); //preserve index or whatever the second part of a namereference is m.Write(p.raw, 32 + i * 8, 4); } } else { m.Write(p.raw, 28, size - 4); } break; default: case "DelegateProperty": throw new NotImplementedException(type); } }
private static PropertyValue ReadValue(PCCObject pcc, byte[] raw, int start, int type) { PropertyValue v = new PropertyValue(); switch (pcc.Names[type]) { case "IntProperty": case "FloatProperty": case "ObjectProperty": case "StringRefProperty": v.IntValue = BitConverter.ToInt32(raw, start); v.len = 4; break; case "NameProperty": v.IntValue = BitConverter.ToInt32(raw, start); var nameRef = new NameReference(); nameRef.index = v.IntValue; nameRef.count = BitConverter.ToInt32(raw, start + 4); nameRef.Name = pcc.getNameEntry(nameRef.index); if (nameRef.count > 0) nameRef.Name += "_" + (nameRef.count - 1); v.NameValue = nameRef; v.len = 8; break; case "BoolProperty": if (start < raw.Length) v.IntValue = raw[start]; v.len = 1; break; } return v; }
private static Type getType(PCCObject pcc, int type) { switch (pcc.getNameEntry(type)) { case "None": return Type.None; case "StructProperty": return Type.StructProperty; case "IntProperty": return Type.IntProperty; case "FloatProperty": return Type.FloatProperty; case "ObjectProperty": return Type.ObjectProperty; case "NameProperty": return Type.NameProperty; case "BoolProperty": return Type.BoolProperty; case "ByteProperty": return Type.ByteProperty; case "ArrayProperty": return Type.ArrayProperty; case "DelegateProperty": return Type.DelegateProperty; case "StrProperty": return Type.StrProperty; case "StringRefProperty": return Type.StringRefProperty; default: return Type.Unknown; } }
public static List<Property> ReadProp(PCCObject pcc, byte[] raw, int start) { Property p; PropertyValue v; int sname; List<Property> result = new List<Property>(); int pos = start; if (raw.Length - pos < 8) return result; int name = (int)BitConverter.ToInt64(raw, pos); if (!pcc.isName(name)) return result; string t = pcc.Names[name]; if (pcc.Names[name] == "None") { p = new Property(); p.Name = name; p.TypeVal = Type.None; p.i = 0; p.offsetval = pos; p.Size = 8; p.Value = new PropertyValue(); p.raw = BitConverter.GetBytes((Int64)name); p.offend = pos + 8; result.Add(p); return result; } int type = (int)BitConverter.ToInt64(raw, pos + 8); int size = BitConverter.ToInt32(raw, pos + 16); int idx = BitConverter.ToInt32(raw, pos + 20); if (!pcc.isName(type) || size < 0 || size >= raw.Length) return result; string tp = pcc.Names[type]; switch (tp) { case "DelegateProperty": p = new Property(); p.Name = name; p.TypeVal = Type.DelegateProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = BitConverter.ToInt32(raw, pos + 28); v.len = size; v.Array = new List<PropertyValue>(); pos += 24; for (int i = 0; i < size; i++) { PropertyValue v2 = new PropertyValue(); if (pos < raw.Length) v2.IntValue = raw[pos]; v.Array.Add(v2); pos++; } p.Value = v; break; case "ArrayProperty": int count = (int)BitConverter.ToInt64(raw, pos + 24); p = new Property(); p.Name = name; p.TypeVal = Type.ArrayProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = type; v.len = size - 4; count = v.len;//TODO can be other objects too v.Array = new List<PropertyValue>(); pos += 28; for (int i = 0; i < count; i++) { PropertyValue v2 = new PropertyValue(); if (pos < raw.Length) v2.IntValue = raw[pos]; v.Array.Add(v2); pos++; } p.Value = v; break; case "StrProperty": count = (int)BitConverter.ToInt64(raw, pos + 24); p = new Property(); p.Name = name; p.TypeVal = Type.StrProperty; p.i = 0; p.offsetval = pos + 24; count *= -1; v = new PropertyValue(); v.IntValue = type; v.len = count; pos += 28; string s = ""; for (int i = 0; i < count; i++) { s += (char)raw[pos]; pos += 2; } v.StringValue = s; p.Value = v; break; case "StructProperty": sname = (int)BitConverter.ToInt64(raw, pos + 24); p = new Property(); p.Name = name; p.TypeVal = Type.StructProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = sname; v.len = size; v.Array = new List<PropertyValue>(); pos += 32; for (int i = 0; i < size; i++) { PropertyValue v2 = new PropertyValue(); if (pos < raw.Length) v2.IntValue = raw[pos]; v.Array.Add(v2); pos++; } p.Value = v; break; case "BioMask4Property": p = new Property(); p.Name = name; p.TypeVal = Type.ByteProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.len = size; pos += 24; v.IntValue = raw[pos]; pos += size; p.Value = v; break; case "ByteProperty": sname = (int)BitConverter.ToInt64(raw, pos + 24); p = new Property(); p.Name = name; p.TypeVal = Type.ByteProperty; p.i = 0; p.offsetval = pos + 32; v = new PropertyValue(); v.StringValue = pcc.getNameEntry(sname); v.len = size; pos += 32; if (size == 8) { v.IntValue = BitConverter.ToInt32(raw, pos); } else { v.IntValue = raw[pos]; } pos += size; p.Value = v; break; default: p = new Property(); p.Name = name; p.TypeVal = getType(pcc, type); p.i = 0; p.offsetval = pos + 24; p.Value = ReadValue(pcc, raw, pos + 24, type); pos += p.Value.len + 24; break; } p.Size = size; p.raw = new byte[pos - start]; p.offend = pos; if (pos < raw.Length) for (int i = 0; i < pos - start; i++) p.raw[i] = raw[start + i]; result.Add(p); if (pos != start) result.AddRange(ReadProp(pcc, raw, pos)); return result; }
public static CustomProperty PropertyToGrid(Property p, PCCObject pcc) { string cat = p.TypeVal.ToString(); CustomProperty pg; NameProp pp; switch (p.TypeVal) { case Type.BoolProperty: pg = new CustomProperty(pcc.Names[p.Name], cat, (p.Value.IntValue == 1), typeof(bool), false, true); break; case Type.FloatProperty: byte[] buff = BitConverter.GetBytes(p.Value.IntValue); float f = BitConverter.ToSingle(buff, 0); pg = new CustomProperty(pcc.Names[p.Name], cat, f, typeof(float), false, true); break; case Type.ByteProperty: if (p.Size != 8) { pg = new CustomProperty(pcc.Names[p.Name], cat, (byte)p.Value.IntValue, typeof(byte), false, true); } else { pp = new NameProp(); pp.name = pcc.getNameEntry(p.Value.IntValue); pp.nameindex = p.Value.IntValue; pg = new CustomProperty(pcc.Names[p.Name], cat, pp, typeof(NameProp), false, true); } break; case Type.NameProperty: pp = new NameProp(); pp.name = pcc.getNameEntry(p.Value.IntValue); pp.nameindex = p.Value.IntValue; pg = new CustomProperty(pcc.Names[p.Name], cat, pp, typeof(NameProp), false, true); break; case Type.ObjectProperty: ObjectProp ppo = new ObjectProp(); ppo.objectName = pcc.getObjectName(p.Value.IntValue); ppo.index = p.Value.IntValue; pg = new CustomProperty(pcc.Names[p.Name], cat, ppo, typeof(ObjectProp), false, true); break; case Type.StrProperty: pg = new CustomProperty(pcc.Names[p.Name], cat, p.Value.StringValue, typeof(string), false, true); break; case Type.ArrayProperty: pg = new CustomProperty(pcc.Names[p.Name], cat, BitConverter.ToInt32(p.raw, 24) + " elements", typeof(string), false, true); break; case Type.StructProperty: string structType = pcc.getNameEntry(p.Value.IntValue); if (structType == "Color") { ColorProp cp = new ColorProp(); cp.name = structType; cp.nameindex = p.Value.IntValue; System.Drawing.Color color = System.Drawing.Color.FromArgb(BitConverter.ToInt32(p.raw, 32)); cp.Alpha = color.A; cp.Red = color.R; cp.Green = color.G; cp.Blue = color.B; pg = new CustomProperty(pcc.Names[p.Name], cat, cp, typeof(ColorProp), false, true); } else if (structType == "Vector") { VectorProp vp = new VectorProp(); vp.name = structType; vp.nameindex = p.Value.IntValue; vp.X = BitConverter.ToSingle(p.raw, 32); vp.Y = BitConverter.ToSingle(p.raw, 36); vp.Z = BitConverter.ToSingle(p.raw, 40); pg = new CustomProperty(pcc.Names[p.Name], cat, vp, typeof(VectorProp), false, true); } else if (structType == "Rotator") { RotatorProp rp = new RotatorProp(); rp.name = structType; rp.nameindex = p.Value.IntValue; rp.Pitch = (float)BitConverter.ToInt32(p.raw, 32) * 360f / 65536f; rp.Yaw = (float)BitConverter.ToInt32(p.raw, 36) * 360f / 65536f; rp.Roll = (float)BitConverter.ToInt32(p.raw, 40) * 360f / 65536f; pg = new CustomProperty(pcc.Names[p.Name], cat, rp, typeof(RotatorProp), false, true); } else if (structType == "LinearColor") { LinearColorProp lcp = new LinearColorProp(); lcp.name = structType; lcp.nameindex = p.Value.IntValue; lcp.Red = BitConverter.ToSingle(p.raw, 32); lcp.Green = BitConverter.ToSingle(p.raw, 36); lcp.Blue = BitConverter.ToSingle(p.raw, 40); lcp.Alpha = BitConverter.ToSingle(p.raw, 44); pg = new CustomProperty(pcc.Names[p.Name], cat, lcp, typeof(VectorProp), false, true); } else { StructProp ppp = new StructProp(); ppp.name = structType; ppp.nameindex = p.Value.IntValue; byte[] buf = new byte[p.Value.Array.Count()]; for (int i = 0; i < p.Value.Array.Count(); i++) buf[i] = (byte)p.Value.Array[i].IntValue; List<int> buf2 = new List<int>(); for (int i = 0; i < p.Value.Array.Count() / 4; i++) buf2.Add(BitConverter.ToInt32(buf, i * 4)); ppp.data = buf2.ToArray(); pg = new CustomProperty(pcc.Names[p.Name], cat, ppp, typeof(StructProp), false, true); } break; default: pg = new CustomProperty(pcc.Names[p.Name], cat, p.Value.IntValue, typeof(int), false, true); break; } return pg; }
public static string PropertyToText(Property p, PCCObject pcc) { string s = ""; s = "Name: " + pcc.Names[p.Name]; s += " | Type: " + TypeToString((int)p.TypeVal); s += " | Size: " + p.Value.len.ToString(); switch (p.TypeVal) { case Type.StructProperty: s += " \"" + pcc.getNameEntry(p.Value.IntValue) + "\" with " + p.Value.Array.Count.ToString() + " bytes"; break; case Type.IntProperty: case Type.ObjectProperty: case Type.BoolProperty: case Type.StringRefProperty: s += " Value: " + p.Value.IntValue.ToString(); break; case Type.FloatProperty: byte[] buff = BitConverter.GetBytes(p.Value.IntValue); float f = BitConverter.ToSingle(buff, 0); s += " | Value: " + f.ToString(); break; case Type.NameProperty: s += " " + pcc.Names[p.Value.IntValue]; break; case Type.ByteProperty: s += " | Value: \"" + p.Value.StringValue + "\" with \"" + pcc.getNameEntry(p.Value.IntValue) + "\""; break; case Type.ArrayProperty: s += " bytes"; //Value: " + p.Value.Array.Count.ToString() + " Elements"; break; case Type.StrProperty: if (p.Value.StringValue.Length == 0) break; s += " Value: " + p.Value.StringValue.Substring(0, p.Value.StringValue.Length - 1); break; } return s; }
public static List <Property> ReadProp(PCCObject pcc, byte[] raw, int start) { Property p; PropertyValue v; int sname; List <Property> result = new List <Property>(); int pos = start; if (raw.Length - pos < 8) { return(result); } int name = (int)BitConverter.ToInt64(raw, pos); if (!pcc.isName(name)) { return(result); } string t = pcc.Names[name]; if (pcc.Names[name] == "None") { p = new Property(); p.Name = name; p.TypeVal = Type.None; p.i = 0; p.offsetval = pos; p.Size = 8; p.Value = new PropertyValue(); p.raw = BitConverter.GetBytes((Int64)name); p.offend = pos + 8; result.Add(p); return(result); } int type = (int)BitConverter.ToInt64(raw, pos + 8); int size = BitConverter.ToInt32(raw, pos + 16); int idx = BitConverter.ToInt32(raw, pos + 20); if (!pcc.isName(type) || size < 0 || size >= raw.Length) { return(result); } string tp = pcc.Names[type]; switch (tp) { case "DelegateProperty": p = new Property(); p.Name = name; p.TypeVal = Type.DelegateProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = BitConverter.ToInt32(raw, pos + 28); v.len = size; v.Array = new List <PropertyValue>(); pos += 24; for (int i = 0; i < size; i++) { PropertyValue v2 = new PropertyValue(); if (pos < raw.Length) { v2.IntValue = raw[pos]; } v.Array.Add(v2); pos++; } p.Value = v; break; case "ArrayProperty": int count = (int)BitConverter.ToInt64(raw, pos + 24); p = new Property(); p.Name = name; p.TypeVal = Type.ArrayProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = type; v.len = size - 4; count = v.len;//TODO can be other objects too v.Array = new List <PropertyValue>(); pos += 28; for (int i = 0; i < count; i++) { PropertyValue v2 = new PropertyValue(); if (pos < raw.Length) { v2.IntValue = raw[pos]; } v.Array.Add(v2); pos++; } p.Value = v; break; case "StrProperty": count = (int)BitConverter.ToInt64(raw, pos + 24); p = new Property(); p.Name = name; p.TypeVal = Type.StrProperty; p.i = 0; p.offsetval = pos + 24; count *= -1; v = new PropertyValue(); v.IntValue = type; v.len = count; pos += 28; string s = ""; for (int i = 0; i < count; i++) { s += (char)raw[pos]; pos += 2; } v.StringValue = s; p.Value = v; break; case "StructProperty": sname = (int)BitConverter.ToInt64(raw, pos + 24); p = new Property(); p.Name = name; p.TypeVal = Type.StructProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = sname; v.len = size; v.Array = new List <PropertyValue>(); pos += 32; for (int i = 0; i < size; i++) { PropertyValue v2 = new PropertyValue(); if (pos < raw.Length) { v2.IntValue = raw[pos]; } v.Array.Add(v2); pos++; } p.Value = v; break; case "BioMask4Property": p = new Property(); p.Name = name; p.TypeVal = Type.ByteProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.len = size; pos += 24; v.IntValue = raw[pos]; pos += size; p.Value = v; break; case "ByteProperty": sname = (int)BitConverter.ToInt64(raw, pos + 24); p = new Property(); p.Name = name; p.TypeVal = Type.ByteProperty; p.i = 0; p.offsetval = pos + 32; v = new PropertyValue(); v.StringValue = pcc.getNameEntry(sname); v.len = size; pos += 32; if (size == 8) { v.IntValue = BitConverter.ToInt32(raw, pos); } else { v.IntValue = raw[pos]; } pos += size; p.Value = v; break; default: p = new Property(); p.Name = name; p.TypeVal = getType(pcc, type); p.i = 0; p.offsetval = pos + 24; p.Value = ReadValue(pcc, raw, pos + 24, type); pos += p.Value.len + 24; break; } p.Size = size; p.raw = new byte[pos - start]; p.offend = pos; if (pos < raw.Length) { for (int i = 0; i < pos - start; i++) { p.raw[i] = raw[start + i]; } } result.Add(p); if (pos != start) { result.AddRange(ReadProp(pcc, raw, pos)); } return(result); }
public static void dumpDynamicMixInsFromPCC(string path) { PCCObject pcc = new PCCObject(path); try { string savepath = Path.GetFileNameWithoutExtension(path) + ".sql"; using (StreamWriter stringoutput = new StreamWriter(savepath)) { int numDone = 1; int numTotal = pcc.Exports.Count; int lastProgress = 0; writeVerboseLine("Enumerating exports"); Boolean needsFlush = false; int index = 0; foreach (PCCObject.ExportEntry exp in pcc.Exports) { index++; //filter switch (exp.ObjectName) { case "AnimNodeSequence": case "BioAnimNodeSequenceMirror": continue; } if (exp.PackageFullName.StartsWith("EffectsMaterials")) { continue; } if (exp.PackageFullName.ToUpper().StartsWith("BIOG")) { continue; } if (exp.PackageFullName.ToUpper().StartsWith("BIOVFX")) { continue; } if (exp.PackageFullName.ToUpper().StartsWith("WWISE")) { continue; } if (exp.PackageFullName.ToUpper().StartsWith("GUI_SF")) { continue; } if (!exp.PackageFullName.Contains("Default__")) { continue; } List<PropertyReader.Property> p; p = PropertyReader.getPropList(pcc, exp); if (p.Count > 0) { Boolean isfirst = true; foreach (Property pr in p) { if (pr.TypeVal == PropertyReader.Type.FloatProperty) { if (isfirst) { stringoutput.WriteLine(" -- EXPORT #" + index + " " + exp.PackageFullName + "." + exp.ObjectName); isfirst = false; } Console.WriteLine("FLOAT PROPERTY: " + pcc.getNameEntry(pr.Name) + " at 0x" + (pr.offsetval + exp.DataOffset).ToString("X8")); byte[] ibuff = BitConverter.GetBytes(pr.Value.IntValue); float f = BitConverter.ToSingle(ibuff, 0); stringoutput.WriteLine("INSERT INTO dynamicmixinlibrary VALUES(null,'CATNAME - " + pcc.getNameEntry(pr.Name) + "'," + "'PLACEHOLDERDESC', 'HINT', 'TARGETMODULE', 'TARGETPATH', " + new FileInfo(pcc.pccFileName).Length.ToString() + "," + "0x" + (pr.offsetval + exp.DataOffset).ToString("X8") + ",3,null,null,null," + f.ToString() + ",null,null,null,null,null,null,0.001,null,CATEGORY, 0);"); } if (pr.TypeVal == PropertyReader.Type.IntProperty) { if (isfirst) { stringoutput.WriteLine(" -- EXPORT #" + index + " " + exp.PackageFullName + "." + exp.ObjectName); isfirst = false; } Console.WriteLine("INT PROPERTY: " + pcc.getNameEntry(pr.Name) + " at 0x" + (pr.offsetval + exp.DataOffset).ToString("X8")); stringoutput.WriteLine("INSERT INTO dynamicmixinlibrary VALUES(null,'CATNAME - " + pcc.getNameEntry(pr.Name) + "'," + "'PLACEHOLDERDESC', 'HINT', 'TARGETMODULE', 'TARGETPATH', " + new FileInfo(pcc.pccFileName).Length.ToString() + "," + "0x" + (pr.offsetval + exp.DataOffset).ToString("X8") + ",0," + pr.Value.IntValue.ToString() + ",null,null,null,0,null,null,null,null,null,0,null,CATEGORY, 0);"); } } } // } // if (data) // { // stringoutput.WriteLine("==============Data=============="); // stringoutput.WriteLine(BitConverter.ToString(exp.Data)); // } //} //numDone++; } //stringoutput.WriteLine("--End of " + datasets); if (needsFlush) { Console.WriteLine(); } } } catch (Exception e) { Console.WriteLine("Exception parsing " + path + "\n" + e.Message); } }
public void GenerateTree(TreeNode localRoot, List <PropHeader> headersList) { foreach (PropHeader header in headersList) { if (readerpos > memory.Length) { throw new IndexOutOfRangeException(": tried to read past bounds of Export Data"); } nodeType type = getType(pcc.getNameEntry(header.type)); if (type != nodeType.ArrayProperty && type != nodeType.StructProperty) { localRoot.Nodes.Add(GenerateNode(header)); } else { if (type == nodeType.ArrayProperty) { TreeNode t = GenerateNode(header); int arrayLength = BitConverter.ToInt32(memory, header.offset + 24); readerpos = header.offset + 28; int tmp = readerpos; UnrealObjectInfo.ArrayType arrayType; try { arrayType = UnrealObjectInfo.getArrayType(className, pcc.getNameEntry(header.name)); } catch (Exception) { arrayType = UnrealObjectInfo.ArrayType.Int; } if (arrayType == UnrealObjectInfo.ArrayType.Struct) { UnrealObjectInfo.PropertyInfo info = UnrealObjectInfo.getPropertyInfo(className, pcc.getNameEntry(header.name)); t.Text = t.Text.Insert(t.Text.IndexOf("Size: ") - 2, $"({info.reference})"); for (int i = 0; i < arrayLength; i++) { readerpos = tmp; int pos = tmp; List <PropHeader> arrayListPropHeaders = ReadHeadersTillNone(); tmp = readerpos; TreeNode n = new TreeNode(i.ToString()); n.Tag = nodeType.ArrayLeafStruct; n.Name = (-pos).ToString(); t.Nodes.Add(n); n = t.LastNode; if (info != null && (UnrealObjectInfo.isImmutable(info.reference) || arrayListPropHeaders.Count == 0)) { readerpos = pos; GenerateSpecialStruct(n, info.reference, header.size / arrayLength); tmp = readerpos; } else if (arrayListPropHeaders.Count > 0) { GenerateTree(n, arrayListPropHeaders); } else { throw new Exception($"at position {readerpos.ToString("X4")}. Could not read element {i} of ArrayProperty {pcc.getNameEntry(header.name)}"); } t.LastNode.Remove(); t.Nodes.Add(n); } localRoot.Nodes.Add(t); } else { t.Text = t.Text.Insert(t.Text.IndexOf("Size: ") - 2, $"({arrayType.ToString()})"); int count = 0; int pos; for (int i = 0; i < (header.size - 4); count++) { pos = header.offset + 28 + i; if (pos > memory.Length) { throw new Exception(": tried to read past bounds of Export Data"); } int val = BitConverter.ToInt32(memory, pos); string s = pos.ToString("X4") + "|" + count + ": "; TreeNode node = new TreeNode(); node.Name = pos.ToString(); if (arrayType == UnrealObjectInfo.ArrayType.Object) { node.Tag = nodeType.ArrayLeafObject; int value = val; if (value == 0) { //invalid s += "Null [" + value + "] "; } else { bool isImport = value < 0; if (isImport) { value = -value; } value--; //0-indexed if (isImport) { if (pcc.Imports.Count > value) { s += pcc.Imports[value].PackageFullName + "." + pcc.Imports[value].ObjectName + " [IMPORT " + value + "]"; } else { s += "Index not in import list [" + value + "]"; } } else { if (pcc.Exports.Count > value) { s += pcc.Exports[value].PackageFullName + "." + pcc.Exports[value].ObjectName + " [EXPORT " + value + "]"; } else { s += "Index not in export list [" + value + "]"; } } } i += 4; } else if (arrayType == UnrealObjectInfo.ArrayType.Name || arrayType == UnrealObjectInfo.ArrayType.Enum) { node.Tag = arrayType == UnrealObjectInfo.ArrayType.Name ? nodeType.ArrayLeafName : nodeType.ArrayLeafEnum; int value = val; if (value < 0) { s += "Invalid Name Index [" + value + "]"; } else { if (pcc.Names.Count > value) { s += $"\"{pcc.Names[value]}\"_{BitConverter.ToInt32(memory, pos + 4)}[NAMEINDEX {value}]"; } else { s += "Index not in name list [" + value + "]"; } } i += 8; } else if (arrayType == UnrealObjectInfo.ArrayType.Float) { node.Tag = nodeType.ArrayLeafFloat; s += BitConverter.ToSingle(memory, pos).ToString("0.0######"); i += 4; } else if (arrayType == UnrealObjectInfo.ArrayType.Byte) { node.Tag = nodeType.ArrayLeafByte; s += "(byte)" + memory[pos]; i += 1; } else if (arrayType == UnrealObjectInfo.ArrayType.Bool) { node.Tag = nodeType.ArrayLeafBool; s += BitConverter.ToBoolean(memory, pos); i += 1; } else if (arrayType == UnrealObjectInfo.ArrayType.String) { node.Tag = nodeType.ArrayLeafString; int sPos = pos + 4; s += "\""; int len = val > 0 ? val : -val; for (int j = 1; j < len; j++) { s += BitConverter.ToChar(memory, sPos); sPos += 2; } s += "\""; i += (len * 2) + 4; } else { node.Tag = nodeType.ArrayLeafInt; s += val.ToString(); i += 4; } node.Text = s; t.Nodes.Add(node); } localRoot.Nodes.Add(t); } } if (type == nodeType.StructProperty) { TreeNode t = GenerateNode(header); readerpos = header.offset + 32; List <PropHeader> ll = ReadHeadersTillNone(); if (ll.Count != 0) { GenerateTree(t, ll); } else { string structType = pcc.getNameEntry(BitConverter.ToInt32(memory, header.offset + 24)); GenerateSpecialStruct(t, structType, header.size); } localRoot.Nodes.Add(t); } } } }
public static void ImportProperty(PCCObject pcc, PCCObject importpcc, Property p, string className, System.IO.MemoryStream m, bool inStruct = false) { string name = importpcc.getNameEntry(p.Name); int idxname = pcc.FindNameOrAdd(name); m.Write(BitConverter.GetBytes(idxname), 0, 4); m.Write(new byte[4], 0, 4); if (name == "None") { return; } string type = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 8)); int idxtype = pcc.FindNameOrAdd(type); m.Write(BitConverter.GetBytes(idxtype), 0, 4); m.Write(new byte[4], 0, 4); string name2; int idxname2; int size, count, pos; List <Property> Props; switch (type) { case "IntProperty": case "FloatProperty": case "ObjectProperty": case "StringRefProperty": m.Write(BitConverter.GetBytes(4), 0, 4); m.Write(new byte[4], 0, 4); m.Write(BitConverter.GetBytes(p.Value.IntValue), 0, 4); break; case "NameProperty": m.Write(BitConverter.GetBytes(8), 0, 4); m.Write(new byte[4], 0, 4); m.Write(BitConverter.GetBytes(pcc.FindNameOrAdd(importpcc.getNameEntry(p.Value.IntValue))), 0, 4); //preserve index or whatever the second part of a namereference is m.Write(p.raw, 28, 4); break; case "BoolProperty": m.Write(new byte[8], 0, 8); m.WriteByte((byte)p.Value.IntValue); break; case "BioMask4Property": m.Write(BitConverter.GetBytes(p.Size), 0, 4); m.Write(new byte[4], 0, 4); m.WriteByte((byte)p.Value.IntValue); break; case "ByteProperty": name2 = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 24)); idxname2 = pcc.FindNameOrAdd(name2); m.Write(BitConverter.GetBytes(p.Size), 0, 4); m.Write(new byte[4], 0, 4); m.Write(BitConverter.GetBytes(idxname2), 0, 4); m.Write(new byte[4], 0, 4); if (p.Size == 8) { m.Write(BitConverter.GetBytes(pcc.FindNameOrAdd(importpcc.getNameEntry(p.Value.IntValue))), 0, 4); m.Write(new byte[4], 0, 4); } else { m.WriteByte(p.raw[32]); } break; case "DelegateProperty": size = BitConverter.ToInt32(p.raw, 16); if (size == 0xC) { name2 = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 28)); idxname2 = pcc.FindNameOrAdd(name2); m.Write(BitConverter.GetBytes(0xC), 0, 4); m.Write(new byte[4], 0, 4); m.Write(new byte[4], 0, 4); m.Write(BitConverter.GetBytes(idxname2), 0, 4); m.Write(new byte[4], 0, 4); } else { m.Write(BitConverter.GetBytes(size), 0, 4); m.Write(new byte[4], 0, 4); for (int i = 0; i < size; i++) { m.WriteByte(p.raw[24 + i]); } } break; case "StrProperty": name2 = p.Value.StringValue; m.Write(BitConverter.GetBytes(4 + name2.Length * 2), 0, 4); m.Write(new byte[4], 0, 4); m.Write(BitConverter.GetBytes(-name2.Length), 0, 4); foreach (char c in name2) { m.WriteByte((byte)c); m.WriteByte(0); } break; case "StructProperty": size = BitConverter.ToInt32(p.raw, 16); name2 = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 24)); idxname2 = pcc.FindNameOrAdd(name2); pos = 32; Props = new List <Property>(); try { Props = ReadProp(importpcc, p.raw, pos); } catch (Exception) { } m.Write(BitConverter.GetBytes(size), 0, 4); m.Write(new byte[4], 0, 4); m.Write(BitConverter.GetBytes(idxname2), 0, 4); m.Write(new byte[4], 0, 4); if (Props.Count == 0 || Props[0].TypeVal == Type.Unknown) { for (int i = 0; i < size; i++) { m.WriteByte(p.raw[32 + i]); } } else { foreach (Property pp in Props) { ImportProperty(pcc, importpcc, pp, className, m, inStruct); } } break; case "ArrayProperty": size = BitConverter.ToInt32(p.raw, 16); count = BitConverter.ToInt32(p.raw, 24); UnrealObjectInfo.PropertyInfo info = UnrealObjectInfo.getPropertyInfo(className, name, inStruct); UnrealObjectInfo.ArrayType arrayType = UnrealObjectInfo.getArrayType(info); pos = 28; List <Property> AllProps = new List <Property>(); if (arrayType == UnrealObjectInfo.ArrayType.Struct) { for (int i = 0; i < count; i++) { Props = new List <Property>(); try { Props = ReadProp(importpcc, p.raw, pos); } catch (Exception) { } AllProps.AddRange(Props); if (Props.Count != 0) { pos = Props[Props.Count - 1].offend; } } } m.Write(BitConverter.GetBytes(size), 0, 4); m.Write(new byte[4], 0, 4); m.Write(BitConverter.GetBytes(count), 0, 4); if (AllProps.Count != 0 && (info == null || !UnrealObjectInfo.isImmutable(info.reference))) { foreach (Property pp in AllProps) { ImportProperty(pcc, importpcc, pp, className, m, inStruct); } } else if (arrayType == UnrealObjectInfo.ArrayType.Name) { for (int i = 0; i < count; i++) { string s = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 28 + i * 8)); m.Write(BitConverter.GetBytes(pcc.FindNameOrAdd(s)), 0, 4); //preserve index or whatever the second part of a namereference is m.Write(p.raw, 32 + i * 8, 4); } } else { m.Write(p.raw, 28, size - 4); } break; default: throw new Exception(type); } }
public static Property getPropOrNull(PCCObject pcc, PCCObject.ExportEntry export, string propName) { List<Property> props = getPropList(pcc, export); foreach (Property prop in props) { if (pcc.getNameEntry(prop.Name) == propName) { return prop; } } return null; }