diff --git a/src/parsing/definitions/nodeParsers/rttiHelpers/rttiValueReaderNative.hpp b/src/parsing/definitions/nodeParsers/rttiHelpers/rttiValueReaderNative.hpp index 863dca0..16f1a74 100644 --- a/src/parsing/definitions/nodeParsers/rttiHelpers/rttiValueReaderNative.hpp +++ b/src/parsing/definitions/nodeParsers/rttiHelpers/rttiValueReaderNative.hpp @@ -207,6 +207,10 @@ class NativeReader throw std::runtime_error(std::format("NativeReader::ReadValue, unknown value type {}", typeName.ToString())); } public: + virtual ~NativeReader() + { + + } virtual void ReadClass(FileCursor& aCursor, Red::ScriptInstance aOut, Red::CBaseRTTIType* aClass) = 0; }; diff --git a/src/parsing/definitions/nodeParsers/scriptable/helpers/nativeScriptableReader.hpp b/src/parsing/definitions/nodeParsers/scriptable/helpers/nativeScriptableReader.hpp index d053a46..3710778 100644 --- a/src/parsing/definitions/nodeParsers/scriptable/helpers/nativeScriptableReader.hpp +++ b/src/parsing/definitions/nodeParsers/scriptable/helpers/nativeScriptableReader.hpp @@ -47,6 +47,7 @@ struct OptimizedFieldHeader class ScriptableReader : redRTTI::native::NativeReader { std::vector* m_names; + static constexpr auto m_reportNonCriticalErrors = false; Red::CName ReadCNameInternal(FileCursor& aCursor) { @@ -155,6 +156,11 @@ class ScriptableReader : redRTTI::native::NativeReader } + virtual ~ScriptableReader() + { + + } + inline std::vector* GetNames() { return m_names; @@ -167,53 +173,42 @@ class ScriptableReader : redRTTI::native::NativeReader const auto baseOffset = aCursor.offset; const auto fieldCount = aCursor.readUShort(); - auto fieldDescriptors = aCursor.ReadMultipleClasses(fieldCount); - std::unordered_map fieldDescMap{}; - - // I'm not sure if this is necessary, given the class will have some default initialization? - - std::transform(fieldDescriptors.begin(), fieldDescriptors.end(), - std::inserter(fieldDescMap, fieldDescMap.end()), - [this](RedPackageFieldHeader aHeader) - { - const auto names = this->GetNames(); - auto optimized = OptimizedFieldHeader::Make(aHeader, names); - return std::make_pair(optimized.m_name, optimized); - }); - - Red::DynArray classProps{}; - - classType->GetProperties(classProps); - - for (auto propData : classProps) + for (auto desc : aCursor.ReadMultipleClasses(fieldCount)) { - // Only bother with loading savable properties - if (propData->flags.isPersistent == 0 && propData->flags.isSavable == 0) - { - continue; - } - - auto saveProp = fieldDescMap.find(propData->name); + const auto propName = m_names->at(desc.m_nameId); + const auto propData = classType->GetProperty(propName); - if (saveProp == fieldDescMap.end()) + // No prop... + if (!propData) { + if constexpr (m_reportNonCriticalErrors) + { + PluginContext::Error(std::format("NativeScriptableReader::ReadClass, couldn't find {}.{}", + classType->GetName().ToString(), propName.ToString())); + } + continue; } - auto storedType = PluginContext::m_rtti->GetType(saveProp->second.m_type); - - if (!storedType || propData->type != storedType) + if (propData->type->GetName() != m_names->at(desc.m_typeId)) { - PluginContext::Error(std::format("NativeScriptableReader::ReadClass, class {}, property type mismatch - {} != {}", - classType->GetName().ToString(), saveProp->second.m_type.ToString(), - propData->type->GetName().ToString())); + if constexpr (m_reportNonCriticalErrors) + { + PluginContext::Error( + std::format("NativeScriptableReader::ReadClass, class {}, property type mismatch - {} != {}", + classType->GetName().ToString(), propData->type->GetName().ToString(), + m_names->at(desc.m_typeId).ToString())); + } continue; } + aCursor.seekTo(FileCursor::SeekTo::Start, baseOffset + desc.m_offset); + auto propPtr = propData->GetValuePtr>(aOut); + try { - ReadValue(aCursor, propPtr, storedType); + ReadValue(aCursor, propPtr, propData->type); } catch (const std::exception& e) { diff --git a/src/parsing/definitions/nodeParsers/scriptable/scriptableContainerNode.hpp b/src/parsing/definitions/nodeParsers/scriptable/scriptableContainerNode.hpp index 47371b2..1db935b 100644 --- a/src/parsing/definitions/nodeParsers/scriptable/scriptableContainerNode.hpp +++ b/src/parsing/definitions/nodeParsers/scriptable/scriptableContainerNode.hpp @@ -7,310 +7,338 @@ #include #include -#include #include +#include #include -#include "helpers/rttiClassCreator.hpp" -#include "helpers/nativeScriptableReader.hpp" -#include "helpers/classDefinitions/playerDevelopmentData.hpp" #include "../defaultNodeData.hpp" +#include "helpers/classDefinitions/playerDevelopmentData.hpp" +#include "helpers/nativeScriptableReader.hpp" +#include "helpers/rttiClassCreator.hpp" -namespace cyberpunk { - struct RedPackageHeader { - std::byte m_version; - std::byte m_unk1; - std::uint16_t m_numSections; - std::uint32_t m_numComponents; - std::uint32_t m_refPoolDescOffset; - std::uint32_t m_refPoolDataOffset; - std::uint32_t m_namePoolDescOffset; - std::uint32_t m_namePoolDataOffset; - std::uint32_t m_chunkDescOffset; - std::uint32_t m_chunkDataOffset; - - static RedPackageHeader FromCursor(FileCursor& aCursor) +namespace cyberpunk +{ +struct RedPackageHeader +{ + std::byte m_version; + std::byte m_unk1; + std::uint16_t m_numSections; + std::uint32_t m_numComponents; + std::uint32_t m_refPoolDescOffset; + std::uint32_t m_refPoolDataOffset; + std::uint32_t m_namePoolDescOffset; + std::uint32_t m_namePoolDataOffset; + std::uint32_t m_chunkDescOffset; + std::uint32_t m_chunkDataOffset; + + static RedPackageHeader FromCursor(FileCursor& aCursor) + { + RedPackageHeader header{}; + + header.m_version = static_cast(aCursor.readByte()); + header.m_unk1 = static_cast(aCursor.readByte()); + + header.m_numSections = aCursor.readUShort(); + header.m_numComponents = aCursor.readUInt(); + + if (header.m_numSections == 7) { - RedPackageHeader header{}; - - header.m_version = static_cast(aCursor.readByte()); - header.m_unk1 = static_cast(aCursor.readByte()); - - header.m_numSections = aCursor.readUShort(); - header.m_numComponents = aCursor.readUInt(); - - if (header.m_numSections == 7) - { - header.m_refPoolDescOffset = aCursor.readUInt(); - header.m_refPoolDataOffset = aCursor.readUInt(); - } - - header.m_namePoolDescOffset = aCursor.readUInt(); - header.m_namePoolDataOffset = aCursor.readUInt(); - - header.m_chunkDescOffset = aCursor.readUInt(); - header.m_chunkDataOffset = aCursor.readUInt(); - - return header; - } - }; - - struct RedPackageImportHeader { - std::uint32_t value; - - static constexpr auto sizeShift = 23; - static constexpr auto offsetMask = (1u << sizeShift) - 1u; - static constexpr auto sizeMask = 0xff << sizeShift; - static constexpr auto syncShift = 31; - - std::uint32_t offset() const { - return value & offsetMask; - } - - std::uint8_t size() const { - return static_cast((value & sizeMask) >> sizeShift); - } - - bool isSync() const { - return value >> syncShift; - } - - RedPackageImportHeader(std::uint32_t bitfield) : value{ bitfield } { - - } - - static RedPackageImportHeader FromCursor(FileCursor& cursor) { - return RedPackageImportHeader{ cursor.readUInt() }; - } - }; - - struct RedPackageNameHeader { - std::uint32_t value; - - static constexpr auto sizeShift = 24; - static constexpr auto offsetMask = 0x00FFFFFF; - static constexpr auto sizeMask = 0xFF000000; - - std::uint32_t offset() const { - return value & offsetMask; - } - - std::uint8_t size() const { - return static_cast((value & sizeMask) >> sizeShift); - } - - RedPackageNameHeader(std::uint32_t bitfield) : value{ bitfield } { - - } + header.m_refPoolDescOffset = aCursor.readUInt(); + header.m_refPoolDataOffset = aCursor.readUInt(); + } + + header.m_namePoolDescOffset = aCursor.readUInt(); + header.m_namePoolDataOffset = aCursor.readUInt(); + + header.m_chunkDescOffset = aCursor.readUInt(); + header.m_chunkDataOffset = aCursor.readUInt(); + + return header; + } +}; + +struct RedPackageImportHeader +{ + std::uint32_t value; + + static constexpr auto sizeShift = 23; + static constexpr auto offsetMask = (1u << sizeShift) - 1u; + static constexpr auto sizeMask = 0xff << sizeShift; + static constexpr auto syncShift = 31; + + std::uint32_t offset() const + { + return value & offsetMask; + } + + std::uint8_t size() const + { + return static_cast((value & sizeMask) >> sizeShift); + } + + bool isSync() const + { + return value >> syncShift; + } + + RedPackageImportHeader(std::uint32_t bitfield) + : value{bitfield} + { + } + + static RedPackageImportHeader FromCursor(FileCursor& cursor) + { + return RedPackageImportHeader{cursor.readUInt()}; + } +}; + +struct RedPackageNameHeader +{ + std::uint32_t value; + + static constexpr auto sizeShift = 24; + static constexpr auto offsetMask = 0x00FFFFFF; + static constexpr auto sizeMask = 0xFF000000; + + std::uint32_t offset() const + { + return value & offsetMask; + } + + std::uint8_t size() const + { + return static_cast((value & sizeMask) >> sizeShift); + } + + RedPackageNameHeader(std::uint32_t bitfield) + : value{bitfield} + { + } + + static RedPackageNameHeader FromCursor(FileCursor& cursor) + { + return RedPackageNameHeader{cursor.readUInt()}; + } +}; + +struct RedImport +{ + enum class ImportFlags + { + Default = 0x0, // done / Load from same archive? + Obligatory = 0x1, // also sync in packages / not used in cr2w currently (1.61) + Template = 0x2, // done / not used in cr2w currently (1.61) + Soft = 0x4, // done / Load from any archive? + Embedded = 0x8, // Load from embedded file + Inplace = 0x10 // done / not used in cr2w currently (1.61) + }; + + std::uint64_t resourcePathHash; + std::string importDepotPath; + ImportFlags importFlags; +}; + +struct RedPackageChunkHeader +{ + std::uint32_t typeId; + std::uint32_t offset; + + static RedPackageChunkHeader FromCursor(FileCursor& cursor) + { + auto ret = RedPackageChunkHeader{}; + + ret.typeId = cursor.readUInt(); + ret.offset = cursor.readUInt(); + + return ret; + } +}; + +struct RedChunk +{ + Red::CName m_typeName; + redRTTI::RTTIValue m_redClass; + + // I do not believe anything non-serializable can be inside scriptablesystem :P + Red::ISerializable* m_instance; + + bool m_isUsed; // For handles, maybe, sometime later... + + // Clean the pointer up + ~RedChunk() + { + if (!m_instance) + { + return; + } - static RedPackageNameHeader FromCursor(FileCursor& cursor) { - return RedPackageNameHeader{ cursor.readUInt() }; - } - }; + if (m_instance->CanBeDestructed()) + { + m_instance->GetType()->Destruct(m_instance); + } + + m_instance->GetAllocator()->Free(m_instance); + } +}; + +class ScriptableSystemsContainerNode : public NodeDataInterface +{ +public: + static constexpr std::wstring_view nodeName = L"ScriptableSystemsContainer"; + static constexpr auto m_enableImports = false; + static constexpr auto m_dumpEnumSizes = false; + + // Won't implement for now, JobQueue is weird and makes me unhappy + // There are better places for optimization anyway + static constexpr auto m_multithreadReading = false; + + RedPackageHeader m_header; + std::vector m_rootCruids; + std::vector m_names; + std::vector m_imports; + std::vector m_chunkHeaders; + std::vector m_chunks; + +private: + RedImport ReadImport(FileCursor& cursor, RedPackageImportHeader importHeader) + { + RedImport ret{}; + + ret.importFlags = importHeader.isSync() ? RedImport::ImportFlags::Obligatory : RedImport::ImportFlags::Default; + ret.importDepotPath = cursor.readString(importHeader.size()); + + return ret; + } + +public: + virtual void ReadData(FileCursor& cursor, NodeEntry& node) + { + const auto dataSize = cursor.readInt(); + if (dataSize == 0) + { + return; + } - struct RedImport { - enum class ImportFlags { - Default = 0x0, // done / Load from same archive? - Obligatory = 0x1, // also sync in packages / not used in cr2w currently (1.61) - Template = 0x2, // done / not used in cr2w currently (1.61) - Soft = 0x4, // done / Load from any archive? - Embedded = 0x8, // Load from embedded file - Inplace = 0x10 // done / not used in cr2w currently (1.61) - }; + { + // Test of less allocation-happy sub-FileCursor creation + auto subCursor = cursor.CreateSubCursor(dataSize); - std::uint64_t resourcePathHash; - std::string importDepotPath; - ImportFlags importFlags; - }; + m_header = RedPackageHeader::FromCursor(subCursor); - struct RedPackageChunkHeader { - std::uint32_t typeId; - std::uint32_t offset; + const auto numCruids = subCursor.readUInt(); - static RedPackageChunkHeader FromCursor(FileCursor& cursor) { - auto ret = RedPackageChunkHeader{}; + for (auto i = 0u; i < numCruids; i++) + { + m_rootCruids.push_back(subCursor.readCruid()); + } - ret.typeId = cursor.readUInt(); - ret.offset = cursor.readUInt(); + const auto baseOffset = subCursor.offset; - return ret; - } - }; + if constexpr (m_enableImports) + { + subCursor.seekTo(FileCursor::SeekTo::Start, baseOffset + m_header.m_refPoolDescOffset); - struct RedChunk { - Red::CName m_typeName; - redRTTI::RTTIValue m_redClass; + const auto refDesc = subCursor.ReadMultipleClasses( + (m_header.m_refPoolDataOffset - m_header.m_refPoolDescOffset) / sizeof(RedPackageImportHeader)); - // I do not believe anything non-serializable can be inside scriptablesystem :P - Red::ISerializable* m_instance; + for (auto ref : refDesc) + { + subCursor.seekTo(FileCursor::SeekTo::Start, baseOffset + ref.offset()); + m_imports.push_back(ReadImport(subCursor, ref)); + } + } - bool m_isUsed; // For handles, maybe, sometime later... + subCursor.seekTo(FileCursor::SeekTo::Start, baseOffset + m_header.m_namePoolDescOffset); + // const auto nameDesc = subCursor.ReadMultipleClasses( + // (m_header.m_namePoolDataOffset - m_header.m_namePoolDescOffset) / sizeof(RedPackageNameHeader)); - // Clean the pointer up - ~RedChunk() - { - if (!m_instance) + for (auto name : subCursor.ReadMultipleClasses( + (m_header.m_namePoolDataOffset - m_header.m_namePoolDescOffset) / sizeof(RedPackageNameHeader))) { - return; - } + subCursor.seekTo(FileCursor::SeekTo::Start, baseOffset + name.offset()); + m_names.push_back(subCursor.ReadCName()); + } - if (m_instance->CanBeDestructed()) - { - m_instance->GetType()->Destruct(m_instance); - } - - m_instance->GetAllocator()->Free(m_instance); - } - }; - - class ScriptableSystemsContainerNode : public NodeDataInterface { - public: - static constexpr std::wstring_view nodeName = L"ScriptableSystemsContainer"; - static constexpr auto m_enableImports = false; - static constexpr auto m_dumpEnumSizes = false; - - RedPackageHeader m_header; - std::vector m_rootCruids; - std::vector m_names; - std::vector m_imports; - std::vector m_chunkHeaders; - std::vector m_chunks; - - private: - RedImport ReadImport(FileCursor& cursor, RedPackageImportHeader importHeader) { - RedImport ret{}; - - ret.importFlags = importHeader.isSync() ? RedImport::ImportFlags::Obligatory : RedImport::ImportFlags::Default; - ret.importDepotPath = cursor.readString(importHeader.size()); - - return ret; - } - - public: - virtual void ReadData(FileCursor& cursor, NodeEntry& node) { - const auto dataSize = cursor.readInt(); - if (dataSize == 0) - { - return; - } + subCursor.seekTo(FileCursor::SeekTo::Start, baseOffset + m_header.m_chunkDescOffset); - { - // Test of less allocation-happy sub-FileCursor creation - auto subCursor = cursor.CreateSubCursor(dataSize); + m_chunkHeaders = subCursor.ReadMultipleClasses( + (m_header.m_chunkDataOffset - m_header.m_chunkDescOffset) / sizeof(RedPackageChunkHeader)); - m_header = RedPackageHeader::FromCursor(subCursor); + scriptable::native::ScriptableReader nativeReader{&m_names}; - const auto numCruids = subCursor.readUInt(); + m_chunks.resize(m_chunkHeaders.size()); - for (auto i = 0u; i < numCruids; i++) { - m_rootCruids.push_back(subCursor.readCruid()); - } + // We could potentially MT this? Chunks aren't particularly related to each other and we don't process + // handles - const auto baseOffset = subCursor.offset; + for (auto i = 0u; i < m_chunkHeaders.size(); i++) + { + auto header = m_chunkHeaders.at(i); + auto& chunk = m_chunks.at(i); - if constexpr (m_enableImports) - { - subCursor.seekTo(FileCursor::SeekTo::Start, baseOffset + m_header.m_refPoolDescOffset); + chunk.m_typeName = m_names.at(header.typeId); - const auto refDesc = subCursor.ReadMultipleClasses( - (m_header.m_refPoolDataOffset - m_header.m_refPoolDescOffset) / sizeof(RedPackageImportHeader)); + auto chunkType = PluginContext::m_rtti->GetType(chunk.m_typeName); - for (auto ref : refDesc) - { - subCursor.seekTo(FileCursor::SeekTo::Start, baseOffset + ref.offset()); - m_imports.push_back(ReadImport(subCursor, ref)); - } - } - - subCursor.seekTo(FileCursor::SeekTo::Start, baseOffset + m_header.m_namePoolDescOffset); - //const auto nameDesc = subCursor.ReadMultipleClasses( - // (m_header.m_namePoolDataOffset - m_header.m_namePoolDescOffset) / sizeof(RedPackageNameHeader)); - - for (auto name : subCursor.ReadMultipleClasses( - (m_header.m_namePoolDataOffset - m_header.m_namePoolDescOffset) / - sizeof(RedPackageNameHeader))) + // We don't know the chunk's type (or the type is wacky), blame mods + if (!chunkType || chunkType->GetType() != Red::ERTTIType::Class) { - subCursor.seekTo(FileCursor::SeekTo::Start, baseOffset + name.offset()); - m_names.push_back(subCursor.ReadCName()); - } + PluginContext::Error(std::format("ScriptableSystemParser: Tried to load chunk {} with no RTTI " + "representation, skipping to next chunk...", + chunk.m_typeName.ToString())); + continue; + } - subCursor.seekTo(FileCursor::SeekTo::Start, baseOffset + m_header.m_chunkDescOffset); + subCursor.seekTo(FileCursor::SeekTo::Start, baseOffset + header.offset); - m_chunkHeaders = subCursor.ReadMultipleClasses( - (m_header.m_chunkDataOffset - m_header.m_chunkDescOffset) / sizeof(RedPackageChunkHeader)); + auto instance = static_cast(chunkType)->CreateInstance(); - scriptable::native::ScriptableReader nativeReader{&m_names}; + nativeReader.ReadClass(subCursor, instance, chunkType); - m_chunks.resize(m_chunkHeaders.size()); + chunk.m_instance = reinterpret_cast(instance); + } - for (auto i = 0u; i < m_chunkHeaders.size(); i++) + // Test what enum sizes actually show up during scriptable reads + if constexpr (m_dumpEnumSizes) + { + for (auto size : scriptable::native::ScriptableReader::s_enumSizes) { - auto header = m_chunkHeaders.at(i); - auto& chunk = m_chunks.at(i); - - chunk.m_typeName = m_names.at(header.typeId); + PluginContext::Spew(std::format("Size {}", static_cast(size))); + } - auto chunkType = PluginContext::m_rtti->GetType(chunk.m_typeName); + std::unordered_set globalEnumSizes{}; - // We don't know the chunk's type (or the type is wacky), blame mods - if (!chunkType || chunkType->GetType() != Red::ERTTIType::Class) + PluginContext::m_rtti->types.ForEach( + [&globalEnumSizes](Red::CName aName, Red::CBaseRTTIType* aType) { - PluginContext::Error(std::format("ScriptableSystemParser: Tried to load chunk {} with no RTTI " - "representation, skipping to next chunk...", - chunk.m_typeName.ToString())); - continue; - } - - subCursor.seekTo(FileCursor::SeekTo::Start, baseOffset + header.offset); - - auto instance = static_cast(chunkType)->CreateInstance(); + if (aType->GetType() == Red::ERTTIType::Enum) + { + globalEnumSizes.insert(static_cast(aType)->actualSize); + } + }); - nativeReader.ReadClass(subCursor, instance, chunkType); + PluginContext::Spew("Enum sizes across all RTTI"); - chunk.m_instance = reinterpret_cast(instance); - } - - // Test what enum sizes actually show up during scriptable reads - if constexpr (m_dumpEnumSizes) + for (auto size : globalEnumSizes) { - for (auto size : scriptable::native::ScriptableReader::s_enumSizes) - { - PluginContext::Spew(std::format("Size {}", static_cast(size))); - } - - std::unordered_set globalEnumSizes{}; - - PluginContext::m_rtti->types.ForEach([&globalEnumSizes](Red::CName aName, Red::CBaseRTTIType* aType) - { - if (aType->GetType() == Red::ERTTIType::Enum) - { - globalEnumSizes.insert(static_cast(aType)->actualSize); - } - }); + PluginContext::Spew(std::format("Size {}", static_cast(size))); + } + } + } + } - PluginContext::Spew("Enum sizes across all RTTI"); + RedChunk& LookupChunk(std::string_view aChunkType) + { + auto chunkIter = + std::find_if(m_chunks.begin(), m_chunks.end(), + [aChunkType](const RedChunk& aChunk) { return aChunk.m_typeName == aChunkType.data(); }); - for (auto size : globalEnumSizes) - { - PluginContext::Spew(std::format("Size {}", static_cast(size))); - } - } - } - } - - RedChunk& LookupChunk(std::string_view aChunkType) { - auto chunkIter = - std::find_if(m_chunks.begin(), m_chunks.end(), - [aChunkType](const RedChunk& aChunk) { - return aChunk.m_typeName == aChunkType.data(); - }); - - if (chunkIter == m_chunks.end()) - { - throw std::runtime_error{std::format("Failed to find chunk {}", aChunkType)}; - } + if (chunkIter == m_chunks.end()) + { + throw std::runtime_error{std::format("Failed to find chunk {}", aChunkType)}; + } - return *chunkIter; - } - }; -} \ No newline at end of file + return *chunkIter; + } +}; +} // namespace cyberpunk \ No newline at end of file diff --git a/wolvenkit/custom_refs.txt b/wolvenkit/custom_refs.txt index 3fe88a8..34fa907 100644 --- a/wolvenkit/custom_refs.txt +++ b/wolvenkit/custom_refs.txt @@ -7,6 +7,7 @@ base\gameplay\gui\fullscreen\new_game_plus\newgameplus_stats_adjustment.inkwidge base\localization\en-us\new_game_plus\new_game_plus_onscreens.json base\localization\en-us\new_game_plus\subtitles\q001\q001_restored_subtitles.json base\localization\en-us\new_game_plus\subtitles\q101\q101_restored_subtitles.json +base\localization\en-us\new_game_plus\subtitles\q116\q116_restored_subtitles.json base\localization\en-us\new_game_plus\subtitles\subtitles.json base\quest\main_quests\part1\q101\scenes\lipsync\en\q101_08_takemura_v_room\civ_high_f_18_jap_25.anims base\quest\main_quests\part1\q101\scenes\lipsync\en\q101_08_takemura_v_room\civ_high_m_20_jap_40.anims @@ -19,6 +20,10 @@ base\quest\main_quests\part1\q101\scenes\lipsync\en\q101_08_takemura_v_room\civ_ base\quest\main_quests\part1\q101\scenes\lipsync\en\q101_08_takemura_v_room\johnny.anims base\quest\main_quests\part1\q101\scenes\lipsync\en\q101_08_takemura_v_room\takemura.anims base\quest\main_quests\part1\q101\scenes\lipsync\en\q101_08_takemura_v_room\v.anims +base\quest\main_quests\part1\q116\scenes\lipsync\en\q116_05_mikoshi\alt.anims +base\quest\main_quests\part1\q116\scenes\lipsync\en\q116_05_mikoshi\jackie.anims +base\quest\main_quests\part1\q116\scenes\lipsync\en\q116_05_mikoshi\johnny.anims +base\quest\main_quests\part1\q116\scenes\lipsync\en\q116_05_mikoshi\v.anims base\quest\NewGamePlus.gamedef mod\quest\changedQuests\NewGamePlus_act_1.questphase mod\quest\changedQuests\NewGamePlus_additional_game_elements.questphase diff --git a/wolvenkit/layout.xml b/wolvenkit/layout.xml index 9c9cda9..263738f 100644 --- a/wolvenkit/layout.xml +++ b/wolvenkit/layout.xml @@ -1 +1 @@ --1095,500,320,940Normal0-11907.333333333333301907.3333333333333173.33333333333334LogViewModelfalsefalseDockfalseBottomLeft1907.3333333333333173.333333333333349090falsetruetruetruefalsetrue-1095,500,320,940false02828000,0,124,50-1false0,0,124,24NormaltrueHorizontalLeft0LeftfalseBottomNormaltruetruetruetruetruetruetruetruefalsefalsefalsefalsefalse001907.3333333333333974909090900falsefalsefalsefalse-1876,755,1528,353Normal0-1370.6666666666667795.3333333333334370.6666666666667354ProjectExplorerViewModelfalsefalseDockfalseTopLeftPropertiesViewModel370.66666666666673549090falsetruetruetruefalsetrue-1876,755,1528,353false02828000,0,124,50-1false0,0,124,24NormaltrueHorizontalLeft0LeftfalseTopNormaltruetruetruetruetruetruetruetruefalsefalsefalsefalsefalse00370.6666666666667795.3333333333334909090900falsefalsefalsefalse676,706,1884,90Normal0-1370.6666666666667795.3333333333334370.6666666666667436PropertiesViewModelfalsefalseDockfalseRightLeft370.66666666666674369090falsetruetruetruefalsetrue676,706,1884,90false02828000,0,124,50-1false0,0,124,24NormaltrueHorizontalLeft0LeftfalseRightNormaltruetruetruetruetruetruetruetruefalsefalsefalsefalsefalse00370.6666666666667795.3333333333334909090900falsefalsefalsefalse52,0,996,948Normal0-11531.333333333333301531.3333333333333288AssetBrowserViewModelfalsefalseDockfalseBottomLeft1531.33333333333332889090falsetruetruetruefalsetrue52,0,996,94844190002false02828000,0,124,50-1false0,0,124,24NormaltrueHorizontalRight0LeftfalseBottomNormaltruetruetruetruetruetruetruetruefalsefalsefalsefalsefalse001531.3333333333333795.3333333333334909090900falsefalsefalsefalse930,355,235,914Normal0-10000TweakBrowserViewModelfalsefalseHiddenfalseRightLeft927.333333333333632.66666666666669090falsetruetruetruefalsetrue930,355,235,91425890496false02828000,0,124,50-1false0,0,124,24NormaltrueHorizontalRight5LeftfalseRightNormaltruetruetruetruetruetruetruetruefalsefalsefalsefalsefalse0000909090900falsefalsefalsefalse1140,610,271.3333333333333,711.3333333333333Normal0-10000LocKeyBrowserViewModelfalsefalseHiddenfalseRightLeft388.66666666666676789090falsetruetruetruefalsetrue1140,610,271.3333333333333,711.333333333333333381819false02828000,0,124,50-1false0,0,124,24NormaltrueHorizontalRight0LeftfalseRightNormaltruetruetruetruetruetruetruetruefalsefalsefalsefalsefalse0000909090900falsefalsefalsefalse \ No newline at end of file +-1095,500,320,940Normal0-12547.333333333333502547.3333333333335173.33333333333334LogViewModelfalsefalseDockfalseBottomLeft1907.3333333333333173.333333333333349090falsetruetruetruefalsetrue-1095,500,320,940false02828000,0,124,50-1false0,0,124,24NormaltrueHorizontalLeft0LeftfalseBottomNormaltruetruetruetruetruetruetruetruefalsefalsefalsefalsefalse001907.3333333333333974909090900falsefalsefalsefalse-1876,755,1528,353Normal0-1495.33333333333331173.9999999999998495.3333333333333524ProjectExplorerViewModelfalsefalseDockfalseTopLeftPropertiesViewModel370.66666666666673549090falsetruetruetruefalsetrue-1876,755,1528,353false02828000,0,124,50-1false0,0,124,24NormaltrueHorizontalLeft0LeftfalseTopNormaltruetruetruetruetruetruetruetruefalsefalsefalsefalsefalse00370.6666666666667795.3333333333334909090900falsefalsefalsefalse676,706,1884,90Normal0-1495.33333333333331173.9999999999998495.3333333333333644.6666666666666PropertiesViewModelfalsefalseDockfalseRightLeft370.66666666666674369090falsetruetruetruefalsetrue676,706,1884,90false02828000,0,124,50-1false0,0,124,24NormaltrueHorizontalLeft0LeftfalseRightNormaltruetruetruetruetruetruetruetruefalsefalsefalsefalsefalse00370.6666666666667795.3333333333334909090900falsefalsefalsefalse52,0,996,948Normal0-12046.666666666666702046.6666666666667288AssetBrowserViewModelfalsefalseDockfalseBottomLeft1531.33333333333332889090falsetruetruetruefalsetrue52,0,996,94844190002false02828000,0,124,50-1false0,0,124,24NormaltrueHorizontalRight0LeftfalseBottomNormaltruetruetruetruetruetruetruetruefalsefalsefalsefalsefalse001531.3333333333333795.3333333333334909090900falsefalsefalsefalse930,355,235,914Normal0-10000TweakBrowserViewModelfalsefalseHiddenfalseRightLeft927.333333333333632.66666666666669090falsetruetruetruefalsetrue930,355,235,91425890496false02828000,0,124,50-1false0,0,124,24NormaltrueHorizontalRight5LeftfalseRightNormaltruetruetruetruetruetruetruetruefalsefalsefalsefalsefalse0000909090900falsefalsefalsefalse1140,610,271.3333333333333,711.3333333333333Normal0-10000LocKeyBrowserViewModelfalsefalseHiddenfalseRightLeft388.66666666666676789090falsetruetruetruefalsetrue1140,610,271.3333333333333,711.333333333333333381819false02828000,0,124,50-1false0,0,124,24NormaltrueHorizontalRight0LeftfalseRightNormaltruetruetruetruetruetruetruetruefalsefalsefalsefalsefalse0000909090900falsefalsefalsefalse \ No newline at end of file diff --git a/wolvenkit/packed/archive/pc/mod/NewGamePlus.archive b/wolvenkit/packed/archive/pc/mod/NewGamePlus.archive index adf985b..013082f 100644 Binary files a/wolvenkit/packed/archive/pc/mod/NewGamePlus.archive and b/wolvenkit/packed/archive/pc/mod/NewGamePlus.archive differ diff --git a/wolvenkit/source/archive/base/localization/en-us/new_game_plus/subtitles/q116/q116_restored_subtitles.json b/wolvenkit/source/archive/base/localization/en-us/new_game_plus/subtitles/q116/q116_restored_subtitles.json new file mode 100644 index 0000000..30fdfdc Binary files /dev/null and b/wolvenkit/source/archive/base/localization/en-us/new_game_plus/subtitles/q116/q116_restored_subtitles.json differ diff --git a/wolvenkit/source/archive/base/localization/en-us/new_game_plus/subtitles/subtitles.json b/wolvenkit/source/archive/base/localization/en-us/new_game_plus/subtitles/subtitles.json index cd35b40..99104a3 100644 Binary files a/wolvenkit/source/archive/base/localization/en-us/new_game_plus/subtitles/subtitles.json and b/wolvenkit/source/archive/base/localization/en-us/new_game_plus/subtitles/subtitles.json differ diff --git a/wolvenkit/source/archive/base/quest/main_quests/part1/q101/scenes/q101_08_takemura_v_room.scene b/wolvenkit/source/archive/base/quest/main_quests/part1/q101/scenes/q101_08_takemura_v_room.scene index 3da0a07..a2768c0 100644 Binary files a/wolvenkit/source/archive/base/quest/main_quests/part1/q101/scenes/q101_08_takemura_v_room.scene and b/wolvenkit/source/archive/base/quest/main_quests/part1/q101/scenes/q101_08_takemura_v_room.scene differ diff --git a/wolvenkit/source/archive/base/quest/main_quests/part1/q116/scenes/q116_05_mikoshi.scene b/wolvenkit/source/archive/base/quest/main_quests/part1/q116/scenes/q116_05_mikoshi.scene new file mode 100644 index 0000000..b335c55 Binary files /dev/null and b/wolvenkit/source/archive/base/quest/main_quests/part1/q116/scenes/q116_05_mikoshi.scene differ diff --git a/wolvenkit/source/archive/base/quest/main_quests/prologue/q001/scenes/q001_00a_before_mission.scene b/wolvenkit/source/archive/base/quest/main_quests/prologue/q001/scenes/q001_00a_before_mission.scene index da695c5..7eb94fc 100644 Binary files a/wolvenkit/source/archive/base/quest/main_quests/prologue/q001/scenes/q001_00a_before_mission.scene and b/wolvenkit/source/archive/base/quest/main_quests/prologue/q001/scenes/q001_00a_before_mission.scene differ