diff --git a/FModel/Creator/Bases/BaseIcon.cs b/FModel/Creator/Bases/BaseIcon.cs index 6561e321..a49c46b2 100644 --- a/FModel/Creator/Bases/BaseIcon.cs +++ b/FModel/Creator/Bases/BaseIcon.cs @@ -62,7 +62,7 @@ namespace FModel.Creator.Bases if (export.GetExport("HeroDefinition", "WeaponDefinition") is { } itemDef) LargeSmallImage.GetPreviewImage(this, itemDef, assetName, forceHR); - else if (export.GetExport(forceHR ? "LargePreviewImage" : "SmallPreviewImage", forceHR ? "ItemDisplayAsset" : "SmallImage") is { } previewImage) + else if (export.GetExport(forceHR ? "LargePreviewImage" : "SmallPreviewImage", forceHR ? "ItemDisplayAsset" : "SmallImage", forceHR ? "SidePanelIcon" : "ToastIcon") is { } previewImage) LargeSmallImage.GetPreviewImage(this, previewImage); else if (export.GetExport("access_item") is { } accessItem) { @@ -109,9 +109,9 @@ namespace FModel.Creator.Bases { } // ^^^^ will return false if image not found, if so, we try to get the normal icon else if (export.GetExport("HeroDefinition", "WeaponDefinition") is { } itemDef) LargeSmallImage.GetPreviewImage(this, itemDef, assetName); - else if (export.GetExport("LargePreviewImage", "SmallPreviewImage", "ItemDisplayAsset") is { } previewImage) + else if (export.GetExport("LargePreviewImage", "SidePanelIcon", "EntryListIcon", "SmallPreviewImage", "ItemDisplayAsset") is { } previewImage) LargeSmallImage.GetPreviewImage(this, previewImage); - else if (export.GetExport("SmallPreviewImage") is { } smallPreviewImage) + else if (export.GetExport("SmallPreviewImage", "ToastIcon") is { } smallPreviewImage) IconImage = Utils.GetObjectTexture(smallPreviewImage); else if (export.GetExport("IconBrush") is { } iconBrush) // abilities LargeSmallImage.GetPreviewImage(this, iconBrush); @@ -119,7 +119,7 @@ namespace FModel.Creator.Bases // text if (export.GetExport("DisplayName", "DefaultHeaderText", "UIDisplayName") is { } displayName) DisplayName = Text.GetTextPropertyBase(displayName); - if (export.GetExport("Description", "DefaultBodyText", "UIDescription", "UIDisplayDescription") is { } description) + if (export.GetExport("Description", "GeneralDescription", "DefaultBodyText", "UIDescription", "UIDisplayDescription") is { } description) Description = Text.GetTextPropertyBase(description); else if (export.GetExport("Description") is { } arrayDescription) // abilities Description = Text.GetTextPropertyBase(arrayDescription); diff --git a/FModel/Creator/Creator.cs b/FModel/Creator/Creator.cs index 70fc7318..7d23a1b9 100644 --- a/FModel/Creator/Creator.cs +++ b/FModel/Creator/Creator.cs @@ -75,6 +75,7 @@ namespace FModel.Creator case "FortStatItemDefinition": case "FortTrapItemDefinition": case "FortAmmoItemDefinition": + case "FortTandemCharacterData": case "FortQuestItemDefinition": case "FortBadgeItemDefinition": case "FortAwardItemDefinition": diff --git a/FModel/PakReader/Parsers/Class/UObject.cs b/FModel/PakReader/Parsers/Class/UObject.cs index d44ba2ab..4405aac1 100644 --- a/FModel/PakReader/Parsers/Class/UObject.cs +++ b/FModel/PakReader/Parsers/Class/UObject.cs @@ -50,8 +50,8 @@ namespace FModel.PakReader.Parsers.Class if (isNonZero) { - var obj = BaseProperty.ReadAsObject(reader, new FPropertyTag(propertyInfo), new FName(propertyInfo.Type), ReadType.NORMAL); var key = Dict.ContainsKey(propertyInfo.Name) ? $"{propertyInfo.Name}_NK{num++:00}" : propertyInfo.Name; + var obj = BaseProperty.ReadAsObject(reader, new FPropertyTag(propertyInfo), new FName(propertyInfo.Type), ReadType.NORMAL); Dict[key] = obj; } else diff --git a/FModel/PakReader/Parsers/IoPackageReader.cs b/FModel/PakReader/Parsers/IoPackageReader.cs index df68e5d5..c2cc2c33 100644 --- a/FModel/PakReader/Parsers/IoPackageReader.cs +++ b/FModel/PakReader/Parsers/IoPackageReader.cs @@ -172,7 +172,7 @@ namespace FModel.PakReader.Parsers } while (it.MoveNext()); } - catch (FileLoadException e) + catch (FileLoadException) { continue; } diff --git a/FModel/PakReader/Parsers/Objects/FFieldClass.cs b/FModel/PakReader/Parsers/Objects/FFieldClass.cs new file mode 100644 index 00000000..e4980848 --- /dev/null +++ b/FModel/PakReader/Parsers/Objects/FFieldClass.cs @@ -0,0 +1,97 @@ +namespace FModel.PakReader.Parsers.Objects +{ + public readonly struct FFieldClass + { + public readonly FName Name; + public readonly ulong Id; + public readonly ulong CastFlags; + public readonly EClassFlags ClassFlags; + + internal FFieldClass(PackageReader reader) + { + Name = reader.ReadFName(); + Id = reader.ReadUInt64(); + CastFlags = reader.ReadUInt64(); + ClassFlags = (EClassFlags)reader.ReadUInt32(); + //TODO finish this + } + } + + public enum EClassFlags : uint + { + /** No Flags */ + CLASS_None = 0x00000000u, + /** Class is abstract and can't be instantiated directly. */ + CLASS_Abstract = 0x00000001u, + /** Save object configuration only to Default INIs, never to local INIs. Must be combined with CLASS_Config */ + CLASS_DefaultConfig = 0x00000002u, + /** Load object configuration at construction time. */ + CLASS_Config = 0x00000004u, + /** This object type can't be saved; null it out at save time. */ + CLASS_Transient = 0x00000008u, + /** Successfully parsed. */ + CLASS_Parsed = 0x00000010u, + /** */ + CLASS_MatchedSerializers = 0x00000020u, + /** Indicates that the config settings for this class will be saved to Project/User*.ini (similar to CLASS_GlobalUserConfig) */ + CLASS_ProjectUserConfig = 0x00000040u, + /** Class is a native class - native interfaces will have CLASS_Native set, but not RF_MarkAsNative */ + CLASS_Native = 0x00000080u, + /** Don't export to C++ header. */ + CLASS_NoExport = 0x00000100u, + /** Do not allow users to create in the editor. */ + CLASS_NotPlaceable = 0x00000200u, + /** Handle object configuration on a per-object basis, rather than per-class. */ + CLASS_PerObjectConfig = 0x00000400u, + + /** Whether SetUpRuntimeReplicationData still needs to be called for this class */ + CLASS_ReplicationDataIsSetUp = 0x00000800u, + + /** Class can be constructed from editinline New button. */ + CLASS_EditInlineNew = 0x00001000u, + /** Display properties in the editor without using categories. */ + CLASS_CollapseCategories = 0x00002000u, + /** Class is an interface **/ + CLASS_Interface = 0x00004000u, + /** Do not export a constructor for this class, assuming it is in the cpptext **/ + CLASS_CustomConstructor = 0x00008000u, + /** all properties and functions in this class are const and should be exported as const */ + CLASS_Const = 0x00010000u, + + /** Class flag indicating the class is having its layout changed, and therefore is not ready for a CDO to be created */ + CLASS_LayoutChanging = 0x00020000u, + + /** Indicates that the class was created from blueprint source material */ + CLASS_CompiledFromBlueprint = 0x00040000u, + + /** Indicates that only the bare minimum bits of this class should be DLL exported/imported */ + CLASS_MinimalAPI = 0x00080000u, + + /** Indicates this class must be DLL exported/imported (along with all of it's members) */ + CLASS_RequiredAPI = 0x00100000u, + + /** Indicates that references to this class default to instanced. Used to be subclasses of UComponent, but now can be any UObject */ + CLASS_DefaultToInstanced = 0x00200000u, + + /** Indicates that the parent token stream has been merged with ours. */ + CLASS_TokenStreamAssembled = 0x00400000u, + /** Class has component properties. */ + CLASS_HasInstancedReference = 0x00800000u, + /** Don't show this class in the editor class browser or edit inline new menus. */ + CLASS_Hidden = 0x01000000u, + /** Don't save objects of this class when serializing */ + CLASS_Deprecated = 0x02000000u, + /** Class not shown in editor drop down for class selection */ + CLASS_HideDropDown = 0x04000000u, + /** Class settings are saved to /..../Blah.ini (as opposed to CLASS_DefaultConfig) */ + CLASS_GlobalUserConfig = 0x08000000u, + /** Class was declared directly in C++ and has no boilerplate generated by UnrealHeaderTool */ + CLASS_Intrinsic = 0x10000000u, + /** Class has already been constructed (maybe in a previous DLL version before hot-reload). */ + CLASS_Constructed = 0x20000000u, + /** Indicates that object configuration will not check against ini base/defaults when serialized */ + CLASS_ConfigDoNotCheckDefaults = 0x40000000u, + /** Class has been consigned to oblivion as part of a blueprint recompile, and a newer version currently exists. */ + CLASS_NewerVersionExists = 0x80000000u, + }; +} diff --git a/FModel/PakReader/Parsers/PropertyTagData/BaseProperty.cs b/FModel/PakReader/Parsers/PropertyTagData/BaseProperty.cs index ba211c18..563579ae 100644 --- a/FModel/PakReader/Parsers/PropertyTagData/BaseProperty.cs +++ b/FModel/PakReader/Parsers/PropertyTagData/BaseProperty.cs @@ -21,6 +21,7 @@ namespace FModel.PakReader.Parsers.PropertyTagData "StrProperty" => new StrProperty(), "TextProperty" => new TextProperty(), "InterfaceProperty" => new InterfaceProperty(), + "FieldPathProperty" => new FieldPathProperty(), //"MulticastDelegateProperty" => new MulticastDelegateProperty(reader, tag), //"LazyObjectProperty" => new LazyObjectProperty(reader, tag), "SoftObjectProperty" => new SoftObjectProperty(), @@ -55,6 +56,7 @@ namespace FModel.PakReader.Parsers.PropertyTagData "StrProperty" => new StrProperty(reader), "TextProperty" => new TextProperty(reader), "InterfaceProperty" => new InterfaceProperty(reader), + "FieldPathProperty" => new FieldPathProperty(reader), //"MulticastDelegateProperty" => new MulticastDelegateProperty(reader, tag), //"LazyObjectProperty" => new LazyObjectProperty(reader, tag), "SoftObjectProperty" => new SoftObjectProperty(reader, readType), @@ -90,6 +92,7 @@ namespace FModel.PakReader.Parsers.PropertyTagData "StrProperty" => new StrProperty(reader).Value, "TextProperty" => new TextProperty(reader).Value, "InterfaceProperty" => new InterfaceProperty(reader).Value, + "FieldPathProperty" => new FieldPathProperty(reader).Value, //"MulticastDelegateProperty" => new MulticastDelegateProperty(reader, tag).Value, //"LazyObjectProperty" => new LazyObjectProperty(reader, tag).Value, "SoftObjectProperty" => new SoftObjectProperty(reader, readType).Value, diff --git a/FModel/PakReader/Parsers/PropertyTagData/FieldPathProperty.cs b/FModel/PakReader/Parsers/PropertyTagData/FieldPathProperty.cs new file mode 100644 index 00000000..30bdd58a --- /dev/null +++ b/FModel/PakReader/Parsers/PropertyTagData/FieldPathProperty.cs @@ -0,0 +1,19 @@ +using FModel.PakReader.Parsers.Objects; + +namespace FModel.PakReader.Parsers.PropertyTagData +{ + public sealed class FieldPathProperty : BaseProperty + { + internal FieldPathProperty() + { + Value = null; + } + internal FieldPathProperty(PackageReader reader) + { + Position = reader.Position; + Value = reader.ReadTArray(() => new FFieldClass(reader)); + } + + public string GetValue() => null; + } +} diff --git a/FModel/ViewModels/Treeview/SortedTreeviewViewModel.cs b/FModel/ViewModels/Treeview/SortedTreeviewViewModel.cs index 53381b90..5095bde5 100644 --- a/FModel/ViewModels/Treeview/SortedTreeviewViewModel.cs +++ b/FModel/ViewModels/Treeview/SortedTreeviewViewModel.cs @@ -131,16 +131,15 @@ namespace FModel.ViewModels.Treeview Assets.Export(pakEntry, true); } } - } - else if (Globals.CachedIoStores.TryGetValue(entry.ContainerFile, out FFileIoStoreReader IoStore)) - { - if (IoStore.TryGetValue("/" + entry.Name.Substring(0, entry.Name.LastIndexOf(".")), out var IoEntry)) // remove the extension to get the entry + else if (Globals.CachedIoStores.TryGetValue(entry.ContainerFile, out FFileIoStoreReader IoStore)) { - Assets.Export(IoEntry, true); + if (IoStore.TryGetValue("/" + entry.Name.Substring(0, entry.Name.LastIndexOf(".")), out var IoEntry)) // remove the extension to get the entry + { + Assets.Export(IoEntry, true); + } } } } - }).ContinueWith(t => { timer.Stop();